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; } }