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]
之间,保证有唯一解,保证答案一定为自然数。
高斯消元的板子,发现会炸long long,取余之后用中国剩余定理确定取值,又发现会爆long long,用慢速乘。
#include<bits/stdc++.h>
using namespace std;
const int Maxn=1005;
#define ll long long
char s[Maxn];
ll x[2][Maxn];
ll n,a[2][Maxn][Maxn];
ll p[2]={1e9+7,1e9+9};
ll ksm(ll a,ll b,ll p){
ll ans=1,ret=a;
for(;b;b>>=1){
if(b&1)(ans*=ret)%=p;
(ret*=ret)%=p;
}
return ans;
}
#define inv(a,p) ksm(a,p-2,p)
void init(){
scanf("%lld",&n);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
ll num;scanf("%lld",&num);
for(int k=0;k<2;++k)
a[k][i][j]=num%p[k];
}
scanf("%s",s+1);
int len=strlen(s+1);
for(int j=1;j<=len;++j)
for(int k=0;k<2;++k)
(((a[k][i][n+1]*=10)%=p[k])+=(s[j]-'0'))%=p[k];
}
}
void gauss(int t,int x){
int mx=a[t][x][x],mxp=0;
for(int i=x+1;i<=n;++i)
if(a[t][i][x]>mx){mx=a[t][i][x];mxp=i;break;}
if(mxp)for(int i=x;i<=n+1;++i)swap(a[t][x][i],a[t][mxp][i]);
ll inv=inv(a[t][x][x],p[t]);
for(int i=x+1;i<=n;++i){
ll kd=a[t][i][x]*inv%p[t];
for(int j=x;j<=n+1;++j)
(((a[t][i][j]-=kd*a[t][x][j])%=p[t])+=p[t])%=p[t];
}
}
void gauss(int t){
for(int i=1;i<n;++i)gauss(t,i);
}
ll mult(ll a,ll b,ll p){
ll ans=0,ret=a;
for(;b;b>>=1){
if(b&1)(ans+=ret)%=p;
(ret<<=1)%=p;
}
return ans;
}
void encode(int t){
for(int i=n;i>=1;--i){
x[t][i]=((a[t][i][n+1]*inv(a[t][i][i],p[t])%p[t])+p[t])%p[t];
for(int j=n;j>=i;--j)
(((a[t][i-1][n+1]-=a[t][i-1][j]*x[t][j])%=p[t])+=p[t])%=p[t];
}
}
ll decode(int idx){
ll ans=0,P=p[0]*p[1];
for(int i=0;i<2;++i){
(ans+=mult(mult(x[i][idx],inv(p[i^1],p[i]),P),p[i^1],P))%=P;
// (((ans+=x[i][idx]*inv(p[i^1],p[i])%P*p[i^1]%P)%=P)+=P)%=P;
}
return (ans%P+P)%P;
}
int main(){
init();
gauss(0);
gauss(1);
encode(0);
encode(1);
for(int i=1;i<=n;++i)
cout<<decode(i)<<'\n';
return 0;
}