bzoj 1220

裴蜀定理

两个数之间:

假设两个数a,b,gcd(a,b)=c

1>证ax+by=d,则c|d,因为c|a&&c|b,所以c|(ax+by),所以c|d.

2>证对于k取任何整数值,总存在x,y使得ax+by=kc,根据扩展欧几里得可以得到这个结论。

3>证根据扩展欧几里得得到的基本解,x1,y1,那么解的范围是x1-kb/c,y1+ka/c,k取任意的整数:首先取另一组解,x2,y2,那么 (y2-y1)/(x1-x2)=(a/c)/(b/c),所以y2-y1=k(a/c),x1-x2=k(b/c),所以其它解与基本解之间满足这个关系,下面证,只要满足这个关系,就是解,只要把x1-kb/c,y1+ka/c带进去就可以证明。

可推广版:

假设两个数a,b,gcd(a,b)=c,假设ax+by的取值范围内最小的正整数是s,即存在x,y使得ax+by=s,下证s==c

设q=|_a/s_|,那么a%s=a-qs=a-q(ax+by)=a(1-qx)-by,可得a%s同样是a和b的一个线性组合,又因为0<=a%s<s,所以a%s只能等于0,所以s|a,同理s|b,所以s|c,s<=c,由上面1>可得,c|s,所以c<=s,所以c==s.


分解一个数n大概只需要sqrt(n)左右的时间:

当遍历完sart(n)时,假设剩下的数是x,它必然是一个质数,证:

假设它不是一个质数,则,则它的素因子必然都大于sqrt(n),而这是不现实的,所以可证。

参考代码:http://www.cnblogs.com/shihuajie/archive/2013/03/25/2980709.html

package a;

import java.math.BigInteger;
import java.util.Scanner;



public class Ha{
	static long n,m;
	static Scanner in=new Scanner(System.in);
	static BigInteger ans=new BigInteger("0");
	static long[] prime=new long[20];
	
	static public BigInteger km(long x,long y){//本来是把y改成BigInteger,结果超时,改回long,就wr了,说明BigInteger虽然好用,但是不能多用,就好像肉一样,好吃,但是不能多吃。还有现在总算知道为什么编译器不出结果了,不出结果但能继续输入,所以以为是编译器坏了,结果是tle
		BigInteger tempans=new BigInteger("1");
		BigInteger tempx=new BigInteger(String.valueOf(x));
		
		while(y!=0){
			if(y%2!=0){
				tempans=tempans.multiply(tempx);
			}
			tempx=tempx.multiply(tempx);
			y=y/2;
		}
		
		return tempans;
	}
	
	static public void main(String args[]){
		n=in.nextLong();
		m=in.nextLong();
		
		long tempm=m;
		int loca=0;
		
		ans=ans.add(km(m,n));
		for(long i=2;i*i<=m;i++){//因为这里m出现在判断条件中,所以m在循环中不能变,这里应该从2开始,否则会陷入死循环
			if(tempm%i==0){
				prime[loca++]=i;
				ans=ans.subtract(km(m/i,n));//把这个放外面了,所以wr了,再次强调,所以写代码时要想意义。
			}
			while(tempm%i==0){
				tempm=tempm/i;
			}
			
		}
		if(tempm!=1){
			prime[loca++]=tempm;
			ans=ans.subtract(km(m/tempm,n));
		}
		
		//System.out.println(loca);
		//System.out.println(ans);
		
		long end=(long)1<<loca;
		for(long i=1;i<end;i++){//因为容斥原理中是任意一个,任意两个,任意三个……,所以应该从1开始,而不是从0开始
			int cou=0;
			long mul=1;
			long tempi=i;
			
			for(int j=0;j<loca;j++){
				if(tempi%2!=0){
					cou++;
					mul=mul*prime[j];
				}
				tempi=tempi/2;
			}
			
			if(cou==1){//这个忘了加
				continue;
			}
			if(cou%2==0){
				ans=ans.add(km(m/mul,n));
			}
			else{
				ans=ans.subtract(km(m/mul,n));
			}
		}
		
		System.out.println(ans);
		
		return;
	}
}


posted @ 2015-09-15 20:16  buzhidaohahaha  阅读(202)  评论(0编辑  收藏  举报