hdu 3571 N-dimensional Sphere(高斯消元+移位乘法)

N-dimensional Sphere

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 670    Accepted Submission(s): 235


Problem Description
In an N-dimensional space, a sphere is defined as {(x1, x2 ... xN)| ∑(xi-Xi)^2 = R^2 (i=1,2,...,N) }. where (X1,X2…XN) is the center. You're given N + 1 points on an N-dimensional sphere and are asked to calculate the center of the sphere.
 

Input
The first line contains an integer T which is the number of test cases.
For each case there's one integer N on the first line.
Each of the N+1 following lines contains N integers x1, x2 ... xN describing the coordinate of a point on the N-dimensional sphere.
(0 <= T <= 10, 1 <= N <= 50, |xi| <= 10^17)
 

Output
For the kth case, first output a line contains “Case k:”, then output N integers on a line indicating the center of the N-dimensional sphere
(It's guaranteed that all coordinate components of the answer are integers and there is only one solution and |Xi| <= 10^17)
 

Sample Input
  
  
2 2 1 0 -1 0 0 1 3 2 2 3 0 2 3 1 3 3 1 2 4
 

Sample Output
  
  
Case 1: 0 0 Case 2: 1 2 3
 

Author
stephydx
 

Source
题目分析:
方程很好求,就是n+1个方程,然后相减,去掉二次项,然后就是利用高斯消元求解,蛋疼的java超时了,然后参照别人的代码用移位乘法做的,过了,主要就是利用同余模定理,因为最后结果给定了范围,所以只需要对2*10^17+3取模,保证是个质数,因为要利用拓展欧几里得求逆元来做除法,然后套到高斯消元的模板当中,高斯消元很简单,就是行列式阶梯型化简,然后再递次向上求解
 
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define MAX 55
#define mod 200000000000000003LL
#define diff 100000000000000000LL

using namespace std;

int n;
typedef long long LL;

LL x[MAX] , g[MAX][MAX] , a[MAX][MAX] , b[MAX][MAX];

LL Mod ( LL x )
{
    if ( x >= mod )
        return x-mod;
    return x;
}

LL mul ( LL a , LL b )
{
    LL ret;
    for ( ret = 0 ; b ; b >>= 1 )
    {
        if ( b&1 ) ret = Mod ( ret + a );
        a = Mod ( a+a );
    }
    return ret;
}

void exgcd ( LL a , LL b , LL& d , LL& x , LL& y )
{
    if ( !b )
        x = 1 , y = 0 , d = a;
    else
        exgcd ( b , a%b , d , y , x ) , y -= (a/b)*x;
}

LL inv ( LL a , LL n )
{
    LL x,y,d;
    exgcd ( a , n , d , x , y );
    return (x%n+n)%n;
}

void Gauss ()
{
    int i,j,k;
    LL v,temp;
    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] )
            {
                temp = mul ( g[j][i],v );
                for ( k = i ; k <= n ; k++ )
                {
                    g[j][k]-=mul(temp,g[i][k]);
                    g[j][k] = ( g[j][k]%mod+mod)%mod;
                }
            }
        }
    }
    for ( i = n-1 ; i >= 0 ; i-- )
    {
        temp = 0;
        for ( j = i+1 ; j < n ; j++ )
        {
            temp += mul ( x[j] , g[i][j] );
            if ( temp >= mod ) temp -= mod;
        }
        temp = g[i][n] - temp;
        temp =(temp%mod+mod)%mod;
        x[i] = mul ( temp , inv ( g[i][i] , mod ) );
    }  
}

int main ( )
{
    int t,c=1;
    LL temp;
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ( "%d" , &n );
        memset ( g , 0 , sizeof ( g ) );
        memset ( b , 0 , sizeof ( b ) );
        for ( int i = 0 ;  i <= n ; i++ )
            for ( int j = 0 ; j < n ; j++ )
            {
                scanf ( "%lld" , &a[i][j] );
                a[i][j] += diff;
                b[i][n] += mul(a[i][j],a[i][j]);
                if ( b[i][n] >= mod ) b[i][n] -= mod;
            }
        for ( int i = 0 ; i < n ; i++ )
        {
            for ( int j = 0 ; j < n ; j++ )
            {
                temp = a[i+1][j] - a[i][j];
                temp = ( temp%mod+mod)%mod;
                g[i][j] = mul ( temp , 2 );
            }
            g[i][n] = b[i+1][n] - b[i][n];
            g[i][n] = (g[i][n]%mod+mod)%mod;
        }
        Gauss();
        printf ( "Case %d:\n", c++ );
        printf ( "%lld" , x[0]-diff );
        for ( int i = 1 ; i < n ; i++ )
            printf ( " %lld" , x[i]-diff );
        printf ( "\n" );
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值