ACM数论小常识
1 1)哥德巴赫猜想: 
一个大于等于4的偶数可以拆分为两个质数的和
(用10e6内的数据测试一下):
#include<iostream>
using namespace std;
#include<conio.h>
#define M 1000000
int p[M];
bool is_prime(int n)
{
    if(n<=1)return false;
    else 
    for(int i=2;i*i<=n;i++)
     if(n%i==0)return false;
     return true;
}
int main()
{
    int n,i,j,k=0;
    for(i=2;i<=M;i++)    
        if(is_prime(i))p[k++]=i;
        printf("%d ",k-1);
    while(1)
    {
        int q=1,s;
        cin>>n;
        if(n<4)printf("输入大于4的数");
        else
        {
          for(i=0;i<=k-1;i++)
            {
                if(p[i]>=n)break;
                for(j=0;j<=k-1;j++)
                {
                 s=p[i]+p[j];
                 if(p[j]>=n)break;
                 if(s==n)
                 {
                     printf("YES\n%d %d\n",p[i],p[j]);
                     q=0;
                     break;
                 }
                }
                if(!q)break;
             }
        }
        if(q)printf("NO\n不存在这两个数\n");
    }
    return 0;
}
1判断组合数C(N,K)是否为奇数 
如果N&K==K则是奇数,反之则为偶数
#include<iostream>
using namespace std;
int fun(int n,int k)
{
    int s=1;
    for(int i=1;i<=k;i++)
    {
        s=s*(n--)/i;        
    }
    return s;
}
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {    
    cout<<fun(n,k)<<endl;
    if((n&k)==k)printf("C(%d,%d)的阶乘为奇数\n",n,k);
    }
    return 0;
}
22N!末尾有多少个0:可以通过数N包含了多少个5,25,125…来计算
所谓零,就是5*2,所以 “n!末尾有多少个零”==“min(n!的质因子中5的数目,n!的质因子中2的数目”
又因为n!的质因子中5的数目必然小于等于2的数目,所以题目就变成了求n!的质因子中5的数目。
比如 26! 是 1*2*3*4*5*6……24*25*26,它们中间有多少个数能被5整除?当然是26/5=5个,但看25,它本身是5*5,也就是25代表着2个5,所以26!尾部零的数目等于 26/5 + 26/25 + 26/125 + ...
现在来计算1000!的末尾有多少个零,那么就是
1000/5 = 200
200/5 = 40 (写成1000/25也可以,但没这个意义了,下同)
40/5 = 8
8/5 = 1
结果就是 200+40+8+1 = 249
#include<iostream>
using namespace std;
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int s=0;
        while(n>=5)
        {
            n/=5;
            s+=n;    
        }
        cout<<s<<"位0"<<endl;
    }
    
    return 0;
}
 求素数方法
memset(vis,0,sizeof(vis));
m=sqrt(1000000);
top=0;
for(i=2;i<=m;i++)
   if(vis[i]==0){
   prime[top++]=i;
   for(j=i*i;j<=n;j+=i)
   vis[j]=1;
}
for(i=m+1;i<1000000;i++)
If(vis[i]==0)
prime[top++]=i;
•1)通常使用足够大的vis[N]数组来打一张表,若vis[p]==0,则p为素数; 
•   vis[p]==1,p不是素数。 
•2)可以把素数都存在prime[]数组里,top是数组中素数的个数。 
•3)4~9行,以i=2为例,所有2的倍数vis[j]都设为1,好像筛选似的吧.其他数类似。 
•4)10~12行,求出(m+1)~1000000内所有的素数。
如何计算a^n ?
•1)计算a*a*a*…*a*a*a,需要计算n-1次乘法,时间复杂度O(n) 
•2)考虑实例a^4,计算b=a*a,再算c=b*b,则c=a^4,但是只用了两次乘法,效率提高。比如a^9=a*(a^4)*(a^4),只需用4次乘法,一般的,a^n时间复杂度为O(logn)
二分法
•数学的魅力: 
•幂运算满足结合律 
•n为偶数: a^n=a^(n/2)*a^(n/2);
•n为奇数: a^n=a^(n/2)*a^(n/2)*a;
•保存a^(n/2),很容易求出a^n; 
大数取模
(a*b)%m=(a%m*b%m )%m; 
求(2^100000000000000)%10000; 
提示:二分法,速度惊人的快速幂!!! 
(a+b)%m=(a%m+b%m)%m; 
若Sn为斐波那契数列前10000项的和, 
求Sn%10000; 
求最大公约数
•辗转相除法 
•int gcd(int a,int b) 
•{ 
•     return b==0?a:gcd(b,a%b); 
•} 
正约数的个数
•已知n=p1^a1*p2^a2…*pk^ak,(也就是n的素数分解),求n的约数个数。 
•分析:n的约数一定包含素因子中的某几项,对于n的某个素因子pi,它在约数中的指数可以是0,1,2…ai共ai+1种情况,根据乘法原理:
•n的约数个数= 
•(a1+1)*(a2+1)…*(ak+1)
欧拉函数
小于n且与n互素的正整数的个数
小于n且与n互素的正整数的个数
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号