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)吗” “唔。。。”
analysis
-
正解BSGS放屁 -
易知倒数第二条式子的答案即为最后的 c c c
-
于是我们可以从一个式子的答案得出该式子真正的 b b b,再推到前一个式子的答案
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 100005
#define ll long long
#define fo(i,a,b) for (register ll i=a;i<=b;i++)
#define fd(i,a,b) for (register ll i=a;i>=b;i--)
using namespace std;
ll a[MAXN],b[MAXN],c[MAXN];
ll n,mod,lastans;
__attribute__((optimize("-O3")))
ll read()
{
ll x=0,f=1;
char ch=getchar();
while (ch<'0' || '9'<ch)
{
if (ch=='-')f=-1;
ch=getchar();
}
while ('0'<=ch && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
__attribute__((optimize("-O3")))
ll pow(ll x,ll y)
{
ll z=1;
while (y)
{
if (y&1)z=z*x%mod;
x=x*x%mod,y/=2;
}
return z%mod;
}
__attribute__((optimize("-O3")))
int main()
{
freopen("dandelion.in","r",stdin);
freopen("dandelion.out","w",stdout);
mod=read();
ll x,y;
while (scanf("%lld%lld",&x,&y)!=EOF)a[++n]=x,b[n]=y;
lastans=b[n--];
fd(i,n,1)
{
c[i]=lastans;
lastans=pow(a[i],lastans)^b[i];
}
fo(i,1,n)printf("%lld\n",c[i]);
return 0;
}