因子和与因子个数的应用:poj 2992+poj 1845+hdu 1452+poj 2480


求解因子和与因子个数的本质是——素因子分解

算法实现:

(1)正因子个数

ll count(ll n)
{
    ll ans=1;
    for(ll i=2;i*i<=n;i++){
        if(n%i==0){
            ll a=0;
            do{
                n/=i;
                a++;
            }while(n%i==0);
            ans=ans*(a+1);
        }
    }
    if(n>1) ans=ans*2;
    return ans;
}

(2)正因子之和

ll sum(ll n)
{
    ll ans=1;
    for(ll i=2;i*i<=n;i++){
        if(n%i==0){
            ll a=1;
            do{
                n/=i;
                a*=i;
            }while(n%i==0);
            ans=ans*(a*i-1)/(i-1);
        }
    }
    if(n>1) ans*=(n+1);
    return ans;
}

poj 2992: Divisors

解题思路:把组合数写成阶乘的形式,以n!为例,小于等于n的prime都是素因子,

利用数论的知识:n!素因子分解中素数p的幂为[n/p]+[n/p^2]+[n/p^3]+[n/p^4]+……

可以求出每个素因子在n!中的幂,+1乘起来就是因子的总个数。

注意:这道题很容易超时,先打表,少用long long

参考代码:

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
#include 
       
       
         #include 
        
          #include 
         
           using namespace std; typedef long long ll; const int maxn = 500; int n,k,t,prime[maxn]; ll ans; bool isprime[maxn]; void getprime() { t=0; memset(isprime,true,sizeof(isprime)); for(int i=2;i<=maxn;i++) { if(isprime[i]){ prime[t++]=i; for(int j=i+i;j<=maxn;j+=i) isprime[j]=false; } } } int count(int n,int p) { int q=p,cnt=0; while(q<=n){ cnt+=n/q; q*=p; } return cnt; } int main() { // freopen("input.txt","r",stdin); getprime();//for(int i=0;i<80;i++) cout< 
          
            <<" "; while(scanf("%d%d",&n,&k)!=EOF){ ans=1; for(int i=0;i 
           
             <=n;i++) ans=ans*(count(n,prime[i])-count(k,prime[i])-count(n-k,prime[i])+1);//因子个数t=(a1+1)*(a2+1)……(an+1); printf("%lld\n",ans); } return 0; } 
            
           
          
         
       
     
     
    
    
   
   

poj 1845: Sumdiv

解题思路:


参考链接:http://blog.csdn.net/lyy289065406/article/details/6648539

参考代码+部分注释:

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
#include 
       
       
         #include 
        
          #include 
         
           using namespace std; typedef long long ll; const int maxn = 500; const ll mod = 9901; ll a,b,t,fac[100],num[100]; ll multi(ll a,ll b); void divide(ll n) //素因子分解 { t=0; memset(num,0,sizeof(num)); for(ll i=2;i*i<=n;i++){ if(n%i==0){ fac[t++]=i; do{ num[t-1]++; n/=i; }while(n%i==0); } } if(n>1) {num[t]++;fac[t++]=n;} return; } ll quickpow_mod(ll a,ll b)//a^b%mod { ll ans=1; while(b){ if(b&1) ans=multi(ans,a); b>>=1; a=multi(a,a); } return ans; } ll multi(ll a,ll b) // a*b%mod { ll ans=0; while(b){ if(b&1) ans=(ans+a)%mod; b>>=1; a=(a+a)%mod; } return ans; } ll sum(ll p,ll n) //递归二分法等比数列求和:1+p+p^2+……+p^n (% m) { if(n==0) return 1; if(n&1) //奇数二分式 (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1)) return multi(sum(p,n/2),1+quickpow_mod(p,n/2+1)); else //偶数二分式 (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2) return (multi(sum(p,n/2-1),1+quickpow_mod(p,n/2+1))+quickpow_mod(p,n/2))%mod; } int main() { // freopen("input.txt","r",stdin); while(cin>>a>>b){ divide(a); ll ans=1; for(int i=0;i 
           
          
         
       
     
     
    
    
   
   

hdu 1452:Happy 2004

参考poj1845的解题思路,先对2004素因子分解,然后递归二分等比数列求和。

参考代码:

#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
#include 
        
        
          #include 
         
           #include 
          
            using namespace std; typedef long long ll; const int maxn = 500; const ll mod = 29; ll X,t,fac[100],num[100]; ll multi(ll a,ll b); void divide(ll n) //素因子分解 { t=0; memset(num,0,sizeof(num)); for(ll i=2;i*i<=n;i++){ if(n%i==0){ fac[t++]=i; do{ num[t-1]++; n/=i; }while(n%i==0); } } if(n>1) {num[t]++;fac[t++]=n;} return; } ll quickpow_mod(ll a,ll b)//a^b%mod { ll ans=1; while(b){ if(b&1) ans=multi(ans,a); b>>=1; a=multi(a,a); } return ans; } ll multi(ll a,ll b) // a*b%mod { ll ans=0; while(b){ if(b&1) ans=(ans+a)%mod; b>>=1; a=(a+a)%mod; } return ans; } ll sum(ll p,ll n) //递归二分法等比数列求和:1+p+p^2+……+p^n (% m) { if(n==0) return 1; if(n&1) //奇数二分式 (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1)) return multi(sum(p,n/2),1+quickpow_mod(p,n/2+1)); else //偶数二分式 (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2) return (multi(sum(p,n/2-1),1+quickpow_mod(p,n/2+1))+quickpow_mod(p,n/2))%mod; } int main() { // freopen("input.txt","r",stdin); divide(2004); while(cin>>X&&X){ ll ans=1; for(int i=0;i 
            
           
          
        
      
      
     
     
    
    

poj  2480: Longge's problem

解题思路:

(数论水平不高,只会这样理解)对于∑gcd(i, n) 1<=i <=n,gcd(i,n)的结果一定是N的因子,首先从gcd(i,N)=1的情况开始考虑,所有的情况个数恰好为欧拉函数值Phi(n);现在我们将其推广到gcd(i,N)=p的情况(p为N的一个因子),那么将n/p后i、n/p互素,gcd(i,N)=p的个数即为欧拉函数值phi(n/p),所以,我们要计算的

∑gcd(i, n)=∑p*phi(n/p),遍历所有因子即可。参考代码如下:

#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
#include 
         
         
           #include 
          
            #include 
           
             using namespace std; typedef long long ll; const int maxn = 1e6+10; ll ans,n; int fac[maxn],t; void divide(ll n) { t=0; for(ll i=1;i*i<=n;i++){ if(n%i==0){ fac[t++]=i; if(i*i 
            
              1) res=res-res/n; return res; } main() { // freopen("input.txt","r",stdin); while(cin>>n){ ans=0; divide(n); for(int i=0;i 
              
             
            
           
         
       
       
      
      
     
     


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值