求助一个诡异的问题
查看原帖
求助一个诡异的问题
546246
E_huanJX泛舟客楼主2022/12/9 11:06

一直 6464 分 RE 调不出来,用 assert 发现 RE 的点会求出 lenth=0,如果加上判定 if(mp.count(val)&&mp[val]!=x) 会 TLE。

首先按照概率,在 2362^{36} 以内随机不应该一直随出一样的 xx 呀。其次后面那份极其相似的代码可以 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;
}
2022/12/9 11:06
加载中...