zoukankan      html  css  js  c++  java
  • bzoj 3122: [Sdoi2013]随机数生成器【BSGS】

    题目要求的是:

    [...a(a(a(ax+b)+b)+b)+b...=a^nx+a^{n-1}b+a^{n-2}b+...+bequiv t(mod p) ]

    后面这一大坨看着不舒服,所以考虑把它化掉,这里有两种做法:

    做法一:两边同乘a-1

    [(a^{n-1}x)(a-1)+b(a^{n-1}-1)equiv t(a-1)(mod p) ]

    [a^nx-a^{n-1}x+ba^{n-1}-b equiv at-t(mod p) ]

    [axa^{n-1}-xa^{a-1}+ba^{n-1} equiv at-t+b(mod p) ]

    [(ax-x+b)a^{n-1} equiv at-t+b(mod p) ]

    [a^{n-1}equiv (at-t+b)inv(ax-x+b)(mod p) ]

    注意这个很容易乘爆,记得随时取模

    做法二:后面乘上a-1的逆元

    [a^{n-1}x+b(a^{n-1}-1)inv(a-1)equiv t(mod p) ]

    [a^{n-1}x+b*a^{n-1}*inv(a-1)-b*inv(a-1)equiv t(mod p) ]

    [a^{n-1}x+b*a^{n-1}*inv(a-1)equiv t+b*inv(a-1)(mod p) ]

    [a^{n-1}(b*inv(a-1)+x)equiv t+b*inv(a-1)(mod p) ]

    [a^{n-1}equiv (t+b*inv(a-1))inv(b*inv(a-1)+x)(mod p) ]

    然后用BSGS解即可,记得加一

    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<cmath>
    using namespace std;
    long long T,p,a,b,x,t,y,z;
    map<long long,long long>mp;
    long long ksm(long long a,long long b)
    {
    	long long r=1ll;
    	a%=p;
    	while(b)
    	{
    		if(b&1)
    			r=r*a%p;
    		a=a*a%p;
    		b>>=1;
    	}
    	return r;
    }
    int main()
    {
    	scanf("%lld",&T);
    	while(T--)
    	{
    		scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x,&t);
    		if(x==t)
    		{
    			puts("1");
    			continue;
    		}
    		if(a==0)
    		{
    			if(b==t)
    				puts("2");
    			else
    				puts("-1");
    			continue;
    		}
    		if(a==1&&b==0)
    		{
    			puts("-1");
    			continue;
    		}
    		if(a==1)
    		{
    			long long now=ksm(b,p-2);
    			printf("%lld
    ",(((t-x)%p+p)%p*now%p+p)%p+1);
    			continue;
    		}
    		y=a,z=((a*t%p-t+b)%p*ksm(a*x-x+b,p-2)%p+p)%p;
    		//y=a,z=((t+b*ksm(a-1,p-2)%p)%p*ksm((x%p+b*ksm(a-1,p-2)%p)%p,p-2))%p;//(a*t-t+b)*ksm(a*x-x+b,p-2);做法二
    		y%=p;
    		if(!y&&!z)
    		{
    			puts("1");
    			continue;
    		}
    		if(!y)
    		{
    			puts("-1");
    			continue;
    		} 
    		mp.clear();
    		long long m=ceil(sqrt(p)),t=1;
    		mp[1]=m+1;
    		for(long long i=1;i<m;i++)
    		{
    			t=t*y%p;
    			if(!mp[t])
    				mp[t]=i;
    		}
    		long long tmp=ksm(y,p-m-1),now=1,f=0;
    		for(long long k=0;k<m;k++)
    		{
    			long long i=mp[z*now%p];
    			if(i) 
    			{
    				if(i==m+1)
    					i=0;
    				printf("%lld
    ",k*m+i+1);
    				f=1;
    				break;
    			}
    			now=now*tmp%p;
    		}
    		if(!f)
    			puts("-1");
    	}
    	return 0;
    }
    
  • 相关阅读:
    P4014 分配问题(网络流24题 最大最小费用流)
    二分图多重匹配
    图论
    小于n的质数的个数(1≤n≤10^11)
    P2341 [HAOI2006]受欢迎的牛| 强连通分量 Tarjan 缩点
    数据库
    树状数组
    C++ 学习笔记
    网络原理
    CG 中点法画直线
  • 原文地址:https://www.cnblogs.com/lokiii/p/8360164.html
Copyright © 2011-2022 走看看