Description
wy 和 wjk 是好朋友。
今天他们在一起聊天,突然聊到了以前一起唱过的《蒲公英的约定》。
“说到蒲公英,我给你讲一个故事吧。”
“嗯?”
“从前有两朵蒲公英,他们约定一起长大,在 N 天内每一天都长出同样多的种子,可是, 他们不想让其他植物知道他们到底要长出多少种子,于是他们中的哥哥想出了一个办法,最 开始,他会告诉弟弟一个数 P,然后在接下来的若干天里每一天哥哥会告诉弟弟两个数:a,c, 然后弟弟在这一天会干如下几件事情:
Step 1:首先把 c 和 lastans 按位异或得到 b,最开始 lastans 是 0
Step 2:如果这天的 b 等于 0,则说明他们已经长出了所有要长出的种子,哥哥与弟弟的交 流结束(输入文件也到此结束)
Step 3:如果这天的 b 不等于 0,弟弟会求出一个最小的非负整数 x 使得(即a^x同余于b模p),[题目保证可以找到这样的 x]
Step 4:lastans 赋值为 x
现在给你哥哥给弟弟的所有数字,你能求出每天弟弟要长出的种子的数量(即每天的 x)吗” “唔。。。”
Input
第一行一个整数 P 接下来若干行(不妨认为有 N+1 行),每行两个整数 a,c,含义如题目描述所示。
Output
一共 N 行,每行一个整数,第 i 行代表第 i 天弟弟要长出的种子的数量(即第 i 天的 x 的值) [第 N+1 天弟弟会在第二步停止,所以不用求出这一天的 x 输出,只作为输入文件结束的标 志]
Sample Input
17
2 8
8 11
5 5
4 12
Sample Output
3
1
12
【样例解释】 [以下 N 行,每行两个整数,第一个整数代表第 i 天的 a,第二个整数代表第 i 天的 b]
2 8
8 8
5 4
4 0
Data Constraint
对于 30%的数据 1 ≤ N ≤ 1000 1 ≤ P ≤ 1000
对于 60%的数据 1 ≤ N ≤ 10000 1 ≤ P ≤ 60000
另有 10%的数据 每一天的 a 都相等
对于 100%的数据 1 ≤ N ≤ 100000 1 ≤ P ≤ 100000 且 P 是素数 a,b ≤ P-1
题解
很显然可以用BSGS,
这样是O(nn)O(n\sqrt n)O(nn)
其实还有更机智的做法,
显然,通过最后一行,
就可以知道上一次的答案,因为它异或c=0,
知道上一次的答案之后,就可以用快速幂求出上一次的b,
通过b跟再上一次的c就可以求出了再上一次的答案。
以此类推。
code
#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 100003
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
int p,n,a[N],b[N],c[N],ans[N];
int ksm(ll x,int y)
{
ll s=1;
for(;y;y>>=1,x=x*x%p)
if(y&1)s=s*x%p;
return s;
}
int main()
{
freopen("dandelion.in","r",stdin);
freopen("dandelion.out","w",stdout);
for(read(p),n=1;scanf("%d",&a[n])!=EOF;n++)read(c[n]);
n--;ans[n-1]=c[n];
for(int i=n-1;i;i--)
{
b[i]=ksm(a[i],ans[i]);
ans[i-1]=b[i]^c[i];
}
for(int i=1;i<n;i++)write(ans[i]),P('\n');
return 0;
}