HDU 3571 N-dimensional Sphere 高斯消元

根据题目意思很容易得出式子,但难点在于数据较大,10^17,且输出为整数。

 

大数模板,java都会超时,可耻地去看了解题报告后发现是对中间过程取模。因为数据都在10^17范围以内,所以结果也在这范围内,找个比它大的素数即可。

 

起初还想不明白,消完元后等式右边的结果还要除以未知数的系数,怎么能用取模呢?又可耻地去看了代码后发现其实可以让系数乘以一个数使其取模后变为1,要求出乘以的那个数则用扩展欧几里得就可以了。这样就不需要除法操作了。思维差距啊……

 

最后一直没搞明白为什么非要把数据都加上一个极大值使得负数变正数。取模等过程中正负应该都无所谓的啊,可改了后就WA。。。求解。

 

#include<iostream> #include<cstring> using namespace std; typedef __int64 ll; ll M,L,data[50][51]; int N; void ini(){ L=(ll)1000000000*100000000; M=L*10+3; } ll mod(ll x){return (x%M+M)%M;} ll multi(ll x,ll y){ ll res=0; while(y){ if(y&1){ res+=x; if(res>=M)res-=M; } x=x<<1; if(x>=M)x-=M; y>>=1; } return res; } void get_data(){ ll temp[51][50]; int i,j; scanf("%d",&N); for(j=0;j<N;j++){ scanf("%I64d",&temp[0][j]); temp[0][j]+=L; } for(i=1;i<=N;i++){ data[i-1][N]=0; for(j=0;j<N;j++){ scanf("%I64d",&temp[i][j]); temp[i][j]+=L; data[i-1][j]=mod(2*(temp[i][j]-temp[i-1][j])); data[i-1][N]+=mod(multi(temp[i][j],temp[i][j])-multi(temp[i-1][j],temp[i-1][j])); data[i-1][N]%=M; } } } void ex_gcd(ll a,ll b,ll &x,ll &y){ if(!b){x=1;y=0;return;} ex_gcd(b,a%b,y,x); y-=x*(a/b); } ll get_val(ll a){ ll x,y; ex_gcd(a,M,x,y); return mod(x); } void run(){ int i,j,a; ll val; for(a=0;a<N;a++){ for(i=a;i<N&&!data[i][a];i++); for(j=a;j<N;j++)swap(data[a][j],data[i][j]); val=get_val(data[a][a]);//使第a行第a项乘以一个数后取余得1 for(j=a;j<=N;j++)data[a][j]=multi(data[a][j],val); for(i=a+1;i<N;i++){ if(!data[i][a])continue; for(j=a+1;j<=N;j++){ data[i][j]=mod(data[i][j]-multi(data[i][a],data[a][j])); } data[i][a]=0; } } for(i=N-1;i>=0;i--){ for(j=i+1;j<N;j++){ data[i][N]=mod(data[i][N]-multi(data[i][j],data[j][N])); } } for(i=0;i<N-1;i++)printf("%I64d ",data[i][N]-L); printf("%I64d/n",data[i][N]-L); } int main(){ ini(); int i,t; scanf("%d",&t); for(i=1;i<=t;i++){ get_data(); printf("Case %d:/n",i); run(); } return 0; }

你可能感兴趣的:(HDU 3571 N-dimensional Sphere 高斯消元)