转载自:http://blog.youkuaiyun.com/acdreamers/article/details/8522384
费马平方和定理:奇质数能表示为两个平方数之和的充分必要条件是该素数被4除余1。
结论(1):如果两个整数都能表示为两个平方数之和,则它们的积也能表示为两个平方数之和。
结论(2):如果一个能表示为两个平方数之和的整数被另一个能表示为两个平方数之和的素数整除,则它们的商也能
表示为两个平方数之和。
定理: 正整数n 能表示为两平方数之和的充要条件,是在它的标准分解式中,形如4k+3的素因数的幂指数是偶数.
分析:其实这个定理不难证明,利用费马平方和定理,可以知道一个奇质数能表示为两个数的平方和的充要条件是
该素数除4余1,那么换句话说就是一个4k+3型的素数一定不能表示为两个整数的平方和,因为素数就可以分
为4k+1型和4k+3型,再利用上面的结论(1),这样很明显只需要4k+3型的素数为偶数个就行了。
详细内容见这里:
http://zh.wikipedia.org/wiki/%E8%B4%B9%E9%A9%AC%E5%B9%B3%E6%96%B9%E5%92%8C%E5%AE%9A%E7%90%86
那么丢番图方程:有多少个解呢?
可以通过下面的公式计算:
,其中
满足当d为偶数时,
,当d为奇数时,
比如,BZOJ的1041题用本方法就很方便。
一些关于平方和的结论:
(1)四平方和定理:每个正整数都可以表示成四个整数的平方数之和。在这个定理中,四个整数中可以有为0的。
(2)正整数n能表示为三个数的平方和的充要条件是n不可以表示为的形式,其中m,k为非负整数。
(3)每一个大于等于170的整数n,都可以表示为五个正整数的平方和。
Timus Online Judge网站上有这么一道题目:1593.Square Country.Version2。
这道题目的输入是一个不大于10^15的正整数,要求计算出该正整数最少能够使用多少个正整数的平方和来表示。这
道题目的时间限制是1秒。根据上面的结论很容易写出代码:
- #include <iostream>
- #include <string.h>
- #include <stdio.h>
- #include <math.h>
- using namespace std;
- typedef long long LL;
- int Solve(LL n)
- {
- int i,k;
- LL tmp;
- while(n%4==0) n>>=2; //先消去所有4的因数
- if(n%8==7) return 4; //如果不能表示为三个整数平方和,那么也就不能表示为两个数的平方和
- for(i=8,tmp=9;tmp<=n;i+=8,tmp+=i) //消去所有素因子的偶次幂
- while(n%tmp==0) n/=tmp;
- if(n==1) return 1;
- if(n%2==0) n>>=1;
- if(n%4==3) return 3;
- for(k=sqrt(n),i=3;i<=k&&n%i;i+=4);
- return i>k? 2:3;
- }
- int main()
- {
- LL n;
- while(cin>>n)
- cout<<Solve(n)<<endl;
- return 0;
- }