10.05练习 高斯消元+中国剩余定理(慢速乘优化+字符串优化)

Description

BB很喜欢玩《文明》,因此它知道很多游戏的攻略。有一个攻略根据城市的N 种资源的数量,对地图上许多位置的城市都计算了一个价值分数并给出了如下公式:
一座城市的价值分数=资源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个整数表示这个城市的价值分数。

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,因为精度炸了,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

posted @ 2018-10-06 15:02  saionjisekai  阅读(108)  评论(0编辑  收藏  举报