一直 64 分 RE 调不出来,用 assert
发现 RE 的点会求出 lenth=0
,如果加上判定 if(mp.count(val)&&mp[val]!=x)
会 TLE。
首先按照概率,在 236 以内随机不应该一直随出一样的 x 呀。其次后面那份极其相似的代码可以 AC。???
求教!!非常感谢!!
RE代码
#include<bits/stdc++.h>
using namespace std;
mt19937_64 rd(time(0));//mt19937_64会生成long long范围整数
typedef long long ll;//需要两数做差,必须有符号,不然小减大就自然溢出了
typedef unsigned long long ull;
unordered_map<ull,ll> mp;//把pair<int,int> 哈希成ull
const int N=30000100,S=266666,s=(1<<18);
char n[N];
ll p;
inline void add(int &x,int y)
{
x+=y;
if(x>=p) x-=p;
}
struct M
{
int a[2][2];
M() {memset(a,0,sizeof a);}
M operator*(const M &b)const
{
M c;
for(int k=0;k<2;k++)
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
add(c.a[i][j],1ll*a[i][k]*b.a[k][j]%p);
return c;
}
}mi[2][S+666];
inline M Val(ll x){ return mi[0][x%s]*mi[1][x/s];}
int main()
{
scanf("%s",n+1);scanf("%lld",&p);
if(n[1]=='0') {puts("0"); return 0;}
if(strlen(n+1)==1&&(n[1]=='1'||n[1]=='2')) {printf("%lld\n",1%p); return 0;}
mi[0][0].a[0][0]=1;
mi[0][0].a[1][1]=1;
mi[1][0].a[0][0]=1;
mi[1][0].a[1][1]=1;
/*
单位矩阵
1 0
0 1
*/
mi[0][1].a[0][1]=1;
mi[0][1].a[1][1]=1;
mi[0][1].a[1][0]=1;
/*
转移矩阵
0 1
1 1
*/
//类似光速幂
for(int i=2;i<=s;i++) mi[0][i]=mi[0][i-1]*mi[0][1];
mi[1][1]=mi[0][s];
for(int i=2;i<=s;i++) mi[1][i]=mi[1][i-1]*mi[1][1];
ll lenth=0;//循环节长度
while(1)
{
ll x=(rd()>>28);//随机的上界选到2^36 64-36=28
M res=Val(x);
ull val=((1ull*res.a[0][0])<<32)+res.a[0][1];
if(mp.count(val)) {lenth=labs(mp[val]-x); break;}
mp[val]=x;
}//生日悖论
ll sum=0;
for(int i=1;n[i];i++) sum=(sum*10+n[i]-'0')%lenth;
printf("%d\n",Val(sum).a[0][1]);
return 0;
}
和这份代码非常相似的,但能 AC 的代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=3e7+10,S=1<<18;
ll mod,len;
char s[N];
unordered_map<ull,ll> mp;
mt19937_64 rnd(time(0));
struct matrix
{
ll a[2][2];
matrix() {memset(a,0,sizeof a);}
matrix operator*(matrix b)
{
matrix c;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
return c;
}
}T[2][S+10];
int main()
{
scanf("%s%lld",s+1,&mod);
T[0][0].a[0][0]=T[0][0].a[1][1]=T[1][0].a[0][0]=T[1][0].a[1][1]=1;
T[0][1].a[0][1]=T[0][1].a[1][0]=T[0][1].a[1][1]=1;
for(int i=2;i<=S;i++) T[0][i]=T[0][i-1]*T[0][1];
T[1][1]=T[0][S];
for(int i=2;i<=S;i++) T[1][i]=T[1][i-1]*T[1][1];
while(1)
{
ll x=(rnd()>>28);
matrix c=T[0][x%S]*T[1][x/S];
ull val=((1ull*c.a[0][0])<<32)|c.a[0][1];
if(mp[val]) {len=abs(mp[val]-x); break;}
mp[val]=x;
}
ll sum=0;
for(int i=1;s[i];i++) sum=(sum*10+s[i]-'0')%len;
printf("%lld\n",(T[0][sum%S]*T[1][sum/S]).a[0][1]);
return 0;
}