[BZOJ3122][Sdoi2013]随机数生成器(BSGS)
2018-01-07 08:50
447 查看
题目:
我是超链接题解:
题目让求 Xi+1=aXi+b (mod p)我们回忆一下数学必修五关于数列的内容,把ta化成一个等比数列是不是好做很多呢?
那么我们画出来的等比数列就是Xi+1+ba−1=a(Xi+ba−1) (mod p)
那么根据等比数列递推公式Xn+ba−1=an−1(X1+ba−1) (mod p)
这里只有an−1是未知的呀,我们移项
an−1≡(Xn+b∗inv(a−1))∗inv(X1+b∗inv(a−1)) (mod p)
然后就是一个裸的BSGS啦
不过要特别注意特判内容,a=0和a=1,这个柿子都没有意义,所以要特判
代码:
#include <cstdio> #include <cmath> #include <map> #define LL long long using namespace std; map<LL,LL> hash; LL p,a,b,x1,xn; LL ksm(LL a,LL k) { LL ans=1;a%=p; for (;k;k>>=1,a=a*a%p) if (k&1) ans=ans*a%p; return ans; } LL bsgs(LL a,LL b,LL p) { if (a%p==0) return -1; hash.clear(); LL m=ceil(sqrt(p)); LL am=ksm(a,m); for (int j=0;j<=m;j++){hash[b]=j; b=b*a%p;} LL mul=1; for (int i=1;i<=m;i++) { mul=mul*am%p; if (hash[mul]) return i*m-hash[mul]+1; } return -1; } int main() { int T;scanf("%d",&T); while(T--) { scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&xn); if (x1==xn) {printf("1\n"); continue;} if (a==0) {if (xn==b) printf("2\n");else printf("-1\n");continue;} if (a==1 && b==0) {printf("-1\n");continue;} if (a==1){ LL nyb=ksm(b,p-2); LL ans=((((xn-x1)%p+p)%p)*nyb%p)%p; printf("%lld\n",ans+1); continue; } LL inv=b%p*ksm(a-1,p-2)%p; LL shou=(xn%p+inv)%p; LL hou=(x1%p+inv)%p;hou=ksm(hou,p-2)%p; LL ans=bsgs(a,shou*hou%p,p); printf("%lld\n",ans); } }
UPD:
后来手写hash了一波,直接就在BZOJ/luogu上光荣上榜了
#include <cstring> #include <cstdio> #include <cmath> #define LL long long using namespace std; const int N=100003; LL p,a,b,x1,xn,v ,c ;int tot,nxt ,point ; void addline(LL z,LL mb){int x=z%N; ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=z; c[tot]=mb;} LL ksm(LL a,LL k) { LL ans=1;a%=p; for (;k;k>>=1,a=a*a%p) if (k&1) ans=ans*a%p; return ans; } LL find(LL mb) { int x=mb%N; for (int i=point[x];i;i=nxt[i]) if (v[i]==mb) return c[i]; return -1; } LL bsgs(LL a,LL b,LL p) { if (a%p==0) return -1; tot=0; memset(point,0,sizeof(point)); LL m=ceil(sqrt(p)); LL am=ksm(a,m); for (int j=0;j<=m;j++){addline(b,j); b=b*a%p;} LL mul=1; for (int i=1;i<=m;i++) { mul=mul*am%p; LL t=find(mul); if (t!=-1) return i*m-t+1; } return -1; } int main() { int T;scanf("%d",&T); while(T--) { scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&xn); if (x1==xn) {printf("1\n"); continue;} if (a==0) {if (xn==b) printf("2\n");else printf("-1\n");continue;} if (a==1 && b==0) {printf("-1\n");continue;} if (a==1){ LL nyb=ksm(b,p-2); LL ans=((((xn-x1)%p+p)%p)*nyb%p)%p; printf("%lld\n",ans+1); continue; } LL inv=b%p*ksm(a-1,p-2)%p; LL shou=(xn%p+inv)%p; LL hou=(x1%p+inv)%p;hou=ksm(hou,p-2)%p; LL ans=bsgs(a,shou*hou%p,p); printf("%lld\n",ans); } }
相关文章推荐
- BZOJ3122 [Sdoi2013]随机数生成器 【BSGS】
- 【bzoj3122】[Sdoi2013]随机数生成器 BSGS
- 【BZOJ 3122】 [Sdoi2013]随机数生成器 (BSGS)
- BZOJ 3122 [Sdoi2013]随机数生成器 BSGS
- BZOJ 3122: [Sdoi2013]随机数生成器 ex_gcd+BSGS
- bzoj 3122 : [Sdoi2013]随机数生成器 BSGS
- [BZOJ3122]-[Sdoi2013]随机数生成器-BSGS+exgcd
- Bzoj 3122 [Sdoi2013]随机数生成器(BSGS+exgcd)
- bzoj 3122: [Sdoi2013]随机数生成器【BSGS】
- 【bzoj3122】[Sdoi2013]随机数生成器 BSGS思想的利用
- bzoj 3122 [Sdoi2013]随机数生成器(逆元,BSGS)
- BZOJ-3122-随机数生成器-SDOI2013-BSGS
- [bzoj3122][SDOI2013]随机数生成器 ——BSGS,数列
- BZOJ-3122-随机数生成器-SDOI2013-BSGS
- [bzoj 3122] [Sdoi2013]随机数生成器:数论,同余,分类讨论,BSGS
- 【BZOJ3122】[Sdoi2013]随机数生成器 BSGS+exgcd+特判
- BZOJ3122 [Sdoi2013]随机数生成器 数论
- bzoj3122 [Sdoi2013]随机数生成器
- bzoj3122【SDOI2013】随机数生成器
- [BZOJ3122][Sdoi2013]随机数生成器(快速幂+BSGS)