Codeforces 542 D. Superhero's Job

http://codeforces.com/problemset/problem/542/D

x = p1^k1 * p2^k2 * p3^k3 * .....  (p1,p2,p3...是素因子)

那么 k 一定是某几个素因子的乘积,且每个素因子的个数都与x相等。

J(x) = 1 + p1^k1 + p2^k2 +...+ p1^k1 * p2^k2 + .... (共 2 ^ q 项)

       = (p1^k1 + 1) * (p2^k2 + 1)*...

由于A的约数个数不多,而一个约数只对应一个素因子,所以有效的素因子也不多,先处理出来。

然后 dp[i][j] 表示前i个素因子能组成A的第j个因子的方案数。


#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #include 
                   using namespace std; #define rep(i,n) for(int i=0; i 
                   
                     = N) break; use[i * pri[j]] = 1; if(i % pri[j] == 0) break; } } } int _fac; ll fac[N]; map 
                    
                      mp; void get_fac(ll n) // 因子 { _fac = 0; for(ll i=1; i*i<=n; i++) if(n % i == 0) { fac[_fac++] = i; if(n / i != i) fac[_fac++] = n / i; } } ll usf_pri[N]; int _usf_pri; void get_usf_pri() // 有效的素因子 { _usf_pri = 0; for(int i=0; i<_fac; i++) { ll tmp = fac[i] - 1; for(int j=0; j<_pri && pri[j] * 1LL * pri[j] <= tmp; j++) { if(tmp % pri[j] != 0) continue; while(tmp % pri[j] == 0) tmp /= pri[j]; if(tmp == 1) usf_pri[_usf_pri++] = pri[j]; break; } if(tmp + 1 == fac[i] && tmp > 1) usf_pri[_usf_pri++] = tmp; } sort(usf_pri,usf_pri+_usf_pri); _usf_pri = unique(usf_pri,usf_pri+_usf_pri) - usf_pri; } ll dp[N]; int get_ans() { mst(dp,0); dp[0] = 1; rep(i,_usf_pri) { for(int j=_fac-1; j>=0; j--) { for(ll a=usf_pri[i]; ; a*=usf_pri[i]) { if(a > fac[j]) break; if(fac[j] % (a + 1) != 0) continue; dp[j] += dp[mp[fac[j] / (a + 1)]]; } } } return (int)dp[_fac-1]; } int main() { get_pri(); ll A; scanf("%I64d",&A); get_fac(A); sort(fac,fac+_fac); for(int i=0; i<_fac; i++) { mp[fac[i]] = i; } get_usf_pri(); printf("%d\n",get_ans()); return 0; } 
                     
                    
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值