zoukankan      html  css  js  c++  java
  • HDU 3571 N-dimensional Sphere

    高斯消元,今天数学死了无数次……

    #include <cstdio> 
    #include <cstring>  
    #include <cmath>  
    #include <iostream>  
    #include <algorithm>  
    #define LL __int64  
    const int maxn=55;  
    #define mod 200000000000000003LL //不能用const来定义。。,不知道为什么,需要是素数  
    #define diff 100000000000000000LL //偏移量,使得数都是整数,方便移位乘法  
    using namespace std;  
    LL x[maxn], g[maxn][maxn], a[maxn][maxn], b[maxn][maxn];  
    int n;  
    LL Mod(LL x)//加法取模,防止超__int64  
    {  
        if(x>=mod)  
            return x-mod;  
        return x;  
    }  
    LL mul(LL a,LL b)//乘法,用移位乘法,同样防止超__int64  
    {  
        LL s;  
        for(s=0;b;b>>=1)  
        {  
            if(b&1)  
                s=Mod(s+a);  
            a=Mod(a+a);  
        }  
        return s;  
    }  
    void gcd(LL a,LL b,LL d,LL &x,LL &y)//拓展的欧几里德定理,求ax+by=gcd(a,b)的一个解  
    {  
        if(!b){d=a;x=1;y=0;}  
        else{gcd(b,a%b,d,y,x);y-=x*(a/b);}  
    }  
    LL inv(LL a,LL n)//求逆,用于除法  
    {  
        LL x,y,d;  
        gcd(a,n,d,x,y);  
        return (x%n+n)%n;  
    }  
    void Gauss()//高斯消元  
    {  
        int i,j,k;  
        LL v,tmp;  
        for(i=0;i<n;i++)  
        {  
            for(j=i;j<n;j++)  
            {  
                if(g[j][i])  
                    break;  
            }  
            if(i!=j)  
            {  
                for(k=i;k<=n;k++)  
                    swap(g[i][k],g[j][k]);  
            }  
            v=inv(g[i][i],mod);  
            for(j=i+1;j<n;j++)  
            {  
                if(g[j][i])  
                {  
                    tmp=mul(g[j][i],v);//相当于g[j][i]/g[i][i]%mod;  
                    for(k=i;k<=n;k++)  
                    {  
                        g[j][k]-=mul(tmp,g[i][k]);  
                        g[j][k]=(g[j][k]%mod+mod)%mod;  
                    }  
                }  
            }  
        }  
        //求出所以的解,存入x数组中  
        for(i=n-1;i>=0;i--)  
        {  
            tmp=0;  
            for(j=i+1;j<n;j++)  
            {  
                tmp+=mul(x[j],g[i][j]);  
                if(tmp>=mod)  
                    tmp-=mod;  
            }  
            tmp=g[i][n]-tmp;  
            tmp=(tmp%mod+mod)%mod;  
            x[i]=mul(tmp,inv(g[i][i],mod));  
        }  
    }  
    int main()  
    {  
        int T,tt=0;  
        int i,j;  
        LL tmp;  
        scanf("%d",&T);  
        while(T--)  
        {  
            scanf("%d",&n);  
            memset(g,0,sizeof(g));  
            memset(b,0,sizeof(b));  
            for(i=0;i<=n;i++)  
            {  
                for(j=0;j<n;j++)  
                {  
                    scanf("%I64d",&a[i][j]);  
                    a[i][j]+=diff;//偏移diff  
                    b[i][n]+=mul(a[i][j],a[i][j]);  
                    if (b[i][n]>=mod)  
                        b[i][n]-=mod;  
                }  
            }  
            for(i=0;i<n;i++)  
            {  
                for(j=0;j<n;j++)  
                {  
                    tmp=a[i+1][j]-a[i][j];  
                    tmp=(tmp%mod+mod)%mod;  
                    g[i][j]=mul(tmp,2);  
                }  
                g[i][n]=b[i+1][n]-b[i][n];  
                g[i][n]=(g[i][n]%mod+mod)%mod;  
            }  
            Gauss();  
            printf("Case %d:
    ",++tt);  
            printf("%I64d",x[0]-diff);//减去先前偏移的值。  
            for (i=1;i<n;i++)  
                printf(" %I64d",x[i]-diff);  
            printf("
    ");  
        }  
        return 0;  
    }  
    /* 
        由题意,列方程组∑(xj-aij)^2=R^2(0<=j<n),共n+1个方程。 
        存在未知数R,以及二次方,需要降次。逐个与上方方程做差,得到n元一次方程组,共n个方程。 
        剩下套高斯消元的模板就OK了。 
        不过这题有几点需要注意: 
        1.未知数是xi<=1e17,所以无法直接乘除。又∑ai*xi=an和∑ai*xi=an(mod n)(0<=i<=n,xi<n)的解相同 
    (乘法和加法取余处理下酒能证明)。所以可以%mod来解决。 
        2.由于需要求逆,所以mod为素数2e17+3。又正常乘法会超过__int64,所以需要用移位乘法。 
        3.为简单化移位,需要乘数,所以需要添加偏移量diff,根据数学运算可知,只要最后结果减去偏移量即可。 
    */  
    
  • 相关阅读:
    无符合条件的记录,SUM函数返回NULL。返回0而不是Null
    Java中的堆栈,队列,链表
    Java集合类的问题
    2014.7.30日结
    我的CSS之路1
    2014.7.27-7.28日结
    LeetCode解题源代码链接集锦一
    2014.7.23日结
    C++之数组声明与初始化
    系统结构之指令
  • 原文地址:https://www.cnblogs.com/forever97/p/3662252.html
Copyright © 2011-2022 走看看