2017.9.25 随机数生成器 失败总结
程序员文章站
2022-03-14 19:57:39
...
、这个题要用bsgs
如果知道bsgs的话化式子就很有方向了
首先把霍纳法则拆成数列
然后得到 x1*a^n + a^n-1 *b+ a^n-2 *b+.. a*b==t (%P)
用等比数列公式,得x1*a^n +b*(a-a^n)/(1-a)==t (%P)
然后就知道怎么做了、把a^n 放在一块 ((a-1)*x1+b)*a^n ==t*(a-1)+b(%P)
然后就是求这个式子最小的n值
其实bsgs就是分块、、设m=根P n=m*i+j
((a-1)*x1+b)*a^(m*i+j)==t*(a-1)+b(%P)
((a-1)*x1+b)*a^(j)==(t*(a-1)+b ) *a^(-m*i ) (%P)
然后由于j 和 i都只有根n个取值,所以可以预处理每个j对应的值,再枚举i 判断即可
由于页数<P,所以直接取模放进map里就可以了,取模一样页数一定也一样
注意:只要空间不卡,一定要开long long!
码(1100ms卡过、):
#include<iostream>
#include<cstdio>
#include<map>
#include<cmath>
using namespace std;
#define ll long long
ll P,x,y,T,t,x1,a,b,xishu,m,i;
map<ll,ll>ma;
ll ksm(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b%2)ans=ans*a%P;
b/=2;
a=a*a%P;
}
return ans;
}
void exgcd(ll a,ll b)
{
if(!b)
{
x=1;
y=0;
return;
}
exgcd(b,a%b);
ll t=x;
x=y;
y=t-(a/b)*y;
}
int main()
{
scanf("%lld",&T);
while(T--)
{
bool jieshu=0;
scanf("%lld%lld%lld%lld%lld",&P,&a,&b,&x1,&t);
if(x1==t)
{
printf("1\n");
continue;
}
if(a==0)
{
if(b==t)printf("2\n");
else printf("-1\n");
continue;
}
if(a==1)
{
if(b>0){
exgcd(b,P);
printf("%lld\n",(x+P)%P*(t-x1+P)%P+1);
}
else printf("-1\n");
continue;
}
xishu=(x1*(a-1)%P+b)%P;
m=sqrt(P)+1;
t=(t*(a-1)%P+b)%P;
for(i=m;i>=1;i--)
{
ma[xishu*ksm(a,i-1)%P]=i;
}
for(i=0;i<=m;i++)
{
ll mi=ksm(a,m*i);
exgcd(mi,P);
mi=ma[(x*t%P+P)%P];
if(mi>0)
{
printf("%lld\n",i*m+mi);
jieshu=1;
break;
}
}
if(jieshu==0)
{
printf("-1\n");
}
ma.clear();
}
}
上一篇: php如何做sql过滤
下一篇: php如何去除nbsp