[NOI2012] 随机数生成器

看题,先骗分,直接模拟:

#include <bits/stdc++.h>
#define ll long long
#define re register
using namespace std;
const int N=800, INF=0x3f3f3f3f;
ll m,a,c,n,g;
ll x[10000000];

int main(){
	cin>>m>>a>>c>>x[0]>>n>>g;
	for(int i=1;i<=n;i++){
		x[i]=(a*x[i-1]+c)%m;
	}
	cout<<x[n]%g<<endl;
	return 0;
}

喜提 \(30Pts\)

然后,也是很明显,因为是一个递推式,所以直接矩阵加速,找个转移矩阵就行(不过刚开始没找对,这个还得加强),然后矩阵快速幂求。

#include <bits/stdc++.h>
#define ll long long
#define re register
using namespace std;
const int N=800, INF=0x3f3f3f3f;
ll mod,a,c,X0,n,g;
ll ans[3][3];
ll A[3][3];
void f1(){
	ll B[3][3]={0};
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			for(int k=1;k<=2;k++)
				B[i][j]=(B[i][j]+(ans[i][k]%mod)*(A[k][j]%mod))%mod;
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			ans[i][j]=B[i][j];
}
void f2(){
	ll B[3][3]={0};
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			for(int k=1;k<=2;k++)
				B[i][j]=(B[i][j]+(A[i][k]%mod)*(A[k][j]%mod))%mod;
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			A[i][j]=B[i][j];
}
ll X(ll k){
	A[1][1]=a;A[1][2]=0;A[2][1]=1;A[2][2]=1;
	ans[1][1]=X0;ans[1][2]=c;
	while(k>0){
		if(k&1)f1();
		f2();
		k>>=1;
	}
	return ans[1][1]%g;
}
int main(){
	cin>>mod>>a>>c>>X0>>n>>g;
	cout<<X(n)<<endl;
	return 0;
}

喜提\(60Pts\)

然后确实不知道问题在哪了,根据题解,还要用快速乘,避免爆炸(雾

#include <bits/stdc++.h>
#define ll long long
#define re register
using namespace std;
const int N=800, INF=0x3f3f3f3f;
ll mod,a,c,X0,n,g;
ll ans[3][3];
ll A[3][3];
ll LowP(ll x,ll y){
	ll ans=0;
	while(y>0){
		if(y&1){
			ans+=x;
			ans%=mod;
		}
		x+=x;
		x%=mod;
		y>>=1;
	}
	return ans;
}
void f1(){
	ll B[3][3]={0};
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			for(int k=1;k<=2;k++)
				B[i][j]=(B[i][j]+LowP(ans[i][k]%mod,A[k][j]%mod))%mod;
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			ans[i][j]=B[i][j];
}
void f2(){
	ll B[3][3]={0};
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			for(int k=1;k<=2;k++)
				B[i][j]=(B[i][j]+LowP(A[i][k]%mod,A[k][j]%mod))%mod;
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			A[i][j]=B[i][j];
}
ll X(ll k){
	A[1][1]=a;A[1][2]=0;A[2][1]=1;A[2][2]=1;
	ans[1][1]=X0;ans[1][2]=c;
	while(k>0){
		if(k&1)f1();
		f2();
		k>>=1;
	}
	return ans[1][1]%g;
}
int main(){
	cin>>mod>>a>>c>>X0>>n>>g;
	cout<<X(n)<<endl;
	return 0;
}

喜提\(100Pts\)

posted @ 2023-07-13 17:55  LsmQwQ  阅读(35)  评论(0)    收藏  举报