40pts WA on #5~#10,悬关
查看原帖
40pts WA on #5~#10,悬关
641153
changbijie_1019楼主2024/5/3 14:15

思路就是矩阵乘法优化DP,开了unsigned long long,但是还是WA

#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int N=29;
int n,MOD,pow10[N];
class Matrix{
	public:
		int r,c,data[N][N];
		Matrix(int rr,int cc){
			r=rr; c=cc;
			memset(data,0,sizeof(data));
		}
		Matrix operator*(const Matrix&m)const{
			Matrix ans(r,m.c);
			for(int i=0;i<=r-1;i++){
				for(int j=0;j<=m.c-1;j++){
					for(int k=0;k<=c-1;k++){
						ans.data[i][j]+=((data[i][k]%MOD)*(m.data[k][j]%MOD))%MOD;
						ans.data[i][j]%=MOD;
					}
				}
			}
			return ans;
		}
		Matrix operator^(int p)const{
			Matrix ans(r,c);
			for(int i=0;i<=r-1;i++) ans.data[i][i]=1;
			Matrix x=*this;
			while(p!=0){
				if(p%2==1) ans=ans*x;
				x=x*x; p/=2;
			}
			return ans;
		}
};
int countdigit(int k){
	int cnt=0;
	do{
		cnt++;
		k/=10;
	}while(k!=0);
	return cnt;
}
signed main(){
	cin>>n>>MOD;
	int bound=countdigit(n);
	pow10[0]=1; for(int i=1;i<=18;i++) pow10[i]=(pow10[i-1]*10)%MOD;
	Matrix ans(3,1);
	ans.data[0][0]=0;
	ans.data[1][0]=0;
	ans.data[2][0]=1;
	for(int digit=1;digit<=bound-1;digit++){
		Matrix p(3,3);
		p.data[0][0]=pow10[digit]; p.data[0][1]=1; p.data[0][2]=1;
		p.data[1][0]=0; p.data[1][1]=1; p.data[1][2]=1;
		p.data[2][0]=0; p.data[2][1]=0; p.data[2][2]=1;
		p=p^(pow10[digit]-pow10[digit-1]);
		ans=p*ans;
	}
	Matrix p(3,3);
	p.data[0][0]=pow10[bound]; p.data[0][1]=1; p.data[0][2]=1;
	p.data[1][0]=0; p.data[1][1]=1; p.data[1][2]=1;
	p.data[2][0]=0; p.data[2][1]=0; p.data[2][2]=1;
	p=p^(n-pow10[bound-1]+1);
	ans=p*ans;
	cout<<ans.data[0][0];
	return 0;
}
2024/5/3 14:15
加载中...