10.05练习 高斯消元+中国剩余定理(慢速乘优化+字符串优化)
Description
BB很喜欢玩《文明》,因此它知道很多游戏的攻略。有一个攻略根据城市的N 种资源的数量,对地图上许多位置的城市都计算了一个价值分数并给出了如下公式:
一座城市的价值分数=资源1的数量*资源1的价值+资源2 的数量*资源2的价值+资源3的数量*资源3的价值+……+资 源N 的数量*资源N 的价值。
然而,SS却是首次接触这个游戏。所以它非常好奇每种资源的价值是如何得出的,于是它找了N 座城市,并获得了这N座城市每座城市N 种资源的数量信息。由于数据量实在很大,因此SS把这些数据给了你。它希望你能帮它算出,每种资源的价值是多少,这样它就能够自己计算出其它城市的价值分数了。
一座城市的价值分数=资源1的数量*资源1的价值+资源2 的数量*资源2的价值+资源3的数量*资源3的价值+……+资 源N 的数量*资源N 的价值。
然而,SS却是首次接触这个游戏。所以它非常好奇每种资源的价值是如何得出的,于是它找了N 座城市,并获得了这N座城市每座城市N 种资源的数量信息。由于数据量实在很大,因此SS把这些数据给了你。它希望你能帮它算出,每种资源的价值是多少,这样它就能够自己计算出其它城市的价值分数了。
Input
输入文件第1 行包含一个整数N,含义如题所述。
第2 行到第N+1 行,每行N+1 个正整数。第i+1 行的第j(j<=N)个整数表示第i 个城市含有资源j的数量,第N+1个整数表示这个城市的价值分数。
第2 行到第N+1 行,每行N+1 个正整数。第i+1 行的第j(j<=N)个整数表示第i 个城市含有资源j的数量,第N+1个整数表示这个城市的价值分数。
Output
输出N行,每行一个整数,第i行的整数表示第i种资源的价值。
Sample Input
1
1 1
Sample Output
1
Hint
数据范围与约定
对于40%的数据,N<=10,每种资源的价值在[0,10^9]之间,资源的数量在[0,128]之间;
对于70%的数据,N<=100;
对于100%的数据,N<=200,每种资源的价值在[0,10^18]之间,资源的数量在[0,10^9]
之间,保证有唯一解,保证答案一定为自然数。
对于40%的数据,N<=10,每种资源的价值在[0,10^9]之间,资源的数量在[0,128]之间;
对于70%的数据,N<=100;
对于100%的数据,N<=200,每种资源的价值在[0,10^18]之间,资源的数量在[0,10^9]
之间,保证有唯一解,保证答案一定为自然数。
直接高斯消元只有40,因为精度炸了,long long也炸了
所以我们取几个模数得出在模下的解,然后用中国剩余定理来求解原来的正解
好多细节55555,感谢HSJ一直帮我调试错误
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 using namespace std; 5 void My(){ 6 freopen("data.in","r",stdin); 7 freopen("my.out","w",stdout); 8 } 9 long long ksm(long long a,long long b,long long mod){ 10 long long ans=1ll; 11 for(;b;b>>=1){ 12 if(b&1){ 13 ans*=a; 14 ans%=mod; 15 } 16 a*=a; 17 a%=mod; 18 } 19 return ans; 20 } 21 long long n,x[205],X[4][300],map[205][205],g[205][205]; 22 long long mul(long long a,long long b,long long mod){ 23 return (a*b-(long long)((long double)a/mod*b)*mod+mod)%mod; 24 } 25 long long A[3],t[3],prime[6]={0,1000000007,1000000009}; 26 void CHN(){ 27 A[1]=prime[2],A[2]=prime[1];long long T=A[1]*A[2]; 28 t[1]=ksm(A[1],prime[1]-2,prime[1]),t[2]=ksm(A[2],prime[2]-2,prime[2]); 29 // cout<<(A[1]*t[1]+A[2]*t[2])%(A[1]*A[2])<<endl; 30 // cout<<"x[1]="<<x[1]<<"\n"; 31 for(long long i=1;i<=n;i++){ 32 for(long long j=1;j<=2;j++){ 33 // cout<<"j="<<j<<" mul="<<(A[j]*t[j])%T<<" "<<X[j][i]<<"\n"; 34 x[i]=(x[i]+mul(mul(A[j],t[j],T),X[j][i],T))%T; 35 // cout<<x[i]<<" 888\n"; 36 } 37 x[i]=(x[i]%T+T)%T; 38 } 39 } 40 void Print(){ 41 for(int i=1;i<=n;i++){ 42 for(int j=1;j<=n+1;j++){ 43 cout<<map[i][j]<<" "; 44 } 45 cout<<'\n'; 46 } 47 } 48 void gauss(long long p){ 49 long long mod=prime[p]; 50 for(long long i=1;i<=n;i++){//消i列 51 long long inv=ksm(map[i][i],mod-2,mod);//B=KA,计算出倍数B/A,可以转化为求逆元就没有精度影响 52 for(long long j=i+1;j<=n;j++){ 53 long long del=mul(map[j][i],inv,mod); 54 for(long long k=i;k<=n+1;k++){ 55 map[j][k]=(map[j][k]-mul(del,map[i][k],mod))%mod; 56 map[j][k]=(map[j][k]%mod+mod)%mod; 57 } 58 } 59 } 60 // Print();cout<<"\n"; 61 for(long long i=n;i>=1;i--){ 62 long long sum=0,inv=ksm(map[i][i],mod-2,mod); 63 for(long long j=n;j>i;j--){ 64 sum=(sum+(mul(X[p][j],map[i][j],mod)))%mod; 65 } 66 X[p][i]=(((map[i][n+1]-sum)%mod+mod)%mod)*inv%mod; 67 } 68 } 69 string S[300]; 70 int main(){ 71 // My(); 72 cin>>n; 73 for(long long i=1;i<=n;i++){ 74 for(long long j=1;j<=n;j++){ 75 cin>>g[i][j]; 76 } 77 cin>>S[i]; 78 } 79 for(long long k=1;k<=2;k++){ 80 for(long long i=1;i<=n;i++){ 81 for(long long j=1;j<=n;j++){ 82 map[i][j]=g[i][j]%prime[k]; 83 // cout<<map[i][j]<<" "; 84 85 } 86 long long x=0; 87 for(int j=0;j<S[i].size();j++)x=(x*10+S[i][j]-'0')%prime[k]; 88 map[i][n+1]=x; 89 // cout<<'\n'; 90 } 91 // cout<<'\n'; 92 gauss(k); 93 } 94 // for(long long i=1;i<=n;i++)cout<<X[1][i]<<endl; 95 CHN(); 96 for(long long i=1;i<=n;i++)cout<<x[i]<<endl; 97 }
over