zoukankan      html  css  js  c++  java
  • HDU 3571 N-dimensional Sphere(高斯消元 数论题)

    这道题算是比较综合的了,要用到扩展欧几里得,乘法二分,高斯消元。

    看了题解才做出来orz

    基本思路是这样,建一个n*(n-1)的行列式,然后高斯消元。

    关键就是在建行列式时会暴long long,所以要用取模来计算,即公式ax=b,等价于ax=b(mod p)

    因为答案范围不超过正负10^17次,p可以取(2*10^17+3)。

    然后加减乘除都能够进行了,乘法用乘法二分来做,除法用模线性方程求逆来做。

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    #define LL __int64
    const LL p=(LL)200000000*1000000000+3;//杭电的编译器不能直接写200000000000000003,会ce
    const LL L=(LL)100000000*1000000000;
    LL ans[60],a[60][60],h[60][60];
    int n;
    LL modans(LL s)//取模
    {
    	if(s<0)
    		s=s+p;
    	else if(s>=p)
    		s=s-p;
    	return s;
    }
    LL calcu(LL base,LL tmp)//乘法二分
    {
        LL ans=0;
    	while(tmp)
    	{
    		if(tmp&1)ans=modans(ans+base);
    		base=modans(base*2);
    		tmp/=2;
    	}
    	return ans;
    }
    void get_h(int s)//每一行初始化
    {
    	int i,j;
    	LL tmp=0;
    	for(i=0;i<n;i++)
    	{
    		h[s][i]=modans(2*(a[s][i]-a[s+1][i]));
    		tmp+=calcu(a[s][i],a[s][i])-calcu(a[s+1][i],a[s+1][i]);
    		tmp=modans(tmp);
    	    //printf("%I64d ",h[s][i]);
    	}
    	h[s][n]=tmp;
    	//printf("%I64d
    ",h[s][n]);
    }
    void init()
    {
    	int i,j;
    	for(i=0;i<n;i++)
    		get_h(i);
    }
    LL extEculid(LL a,LL b,LL &x,LL &y)
    {
    	LL tmp,d;
    	if(b==0){x=1;y=0;return a;}
    	d=extEculid(b,a%b,x,y);
    	tmp=x;x=y;y=tmp-a/b*y;
    	return d;
    }
    void solve()
    {
    	int i,j,k;
    	for(i=0;i<n;i++)//这一步不能落下,当第i行第i个数是0时,要与下面的行互换。这题数据貌似有点水,要是互换后第i个数还是0,就会出错了。。。
    	{
    		for(j=0;j<n;j++)
    			if(h[i][j])
    				break;
    		if(i<j)
    		{
    			for(k=0;k<=n;k++)
    				swap(h[i][k],h[j][k]);
    		}
    	}
    	for(i=0;i<n-1;i++)
    	{
    	  
    	  for(j=i+1;j<n;j++)
    	  {
    		int tmp=h[i][j];
    		for(k=i+1;k<=n;k++)
    			h[j][k]=modans(calcu(h[j][k],h[i][i])-calcu(h[i][k],h[j][i]));
    	  }
    	}
    	LL x,y,g;
    	for(i=n-1;i>=0;i--)
    	{
    		g=extEculid(h[i][i],p,x,y);//由于p是质数,所以g实际上等于1
    		ans[i]=calcu(x,h[i][n]);
    		for(j=0;j<i;j++)
    			h[j][n]=modans(h[j][n]-calcu(h[j][i],ans[i]));
    	}
    }
    int main()
    {
    	int t,i,j;
    	scanf("%d",&t);
    	for(int k=1;k<=t;k++)
    	{
    		scanf("%d",&n);
    		for(i=0;i<=n;i++)
    		for(j=0;j<n;j++)
    		{
    			scanf("%I64d",&a[i][j]);
    			a[i][j]+=L;
    		}
                    init();
    		solve();
    		printf("Case %d:
    ",k);
    		printf("%I64d",(ans[0]-L)%L);
    		for(i=1;i<n;i++)
              printf(" %I64d",(ans[i]-L)%L);
    		printf("
    ");
    	}
    	return 0;
    }


  • 相关阅读:
    Vagrant In Windows 10
    Game Console参数指北
    Java并发编程:volatile关键字解析
    自己实现Linkedlist,实现其常用的增、删、查的方法
    自己实现Arraylsit,实现其常用的几种增、删、该、查的方法
    使用@RequestPart同时上传表单数据和文件(转载)
    Springboot配置跨域访问
    Tesseract-OCR安装使用及样本训练
    Java使用tess4J进行OCR图像识别
    SpringBoot中的静态资源访问(转载)
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3188595.html
Copyright © 2011-2022 走看看