zoukankan      html  css  js  c++  java
  • poj1845 Sumdiv 题解报告

    题目传送门

    【题目大意】

    求$A^B$的所有约数之和($mod 9901$)

    【思路分析】

     把$A$分解质因数,则$$A=p_1^{c_1}*p_2^{c_2}*…*p_n^{c_n}$$

    于是可以得到

    $$A^B=p_1^{B*c_1}*p_2^{B*c_2}*…*p_n^{B*c_n}$$

    于是$A^B$的所有约数之和就是

    $$(1+p_1+…+p_1^{B*c_1})*…*(1+p_n+…+p_n^{B*c_n})$$

    上式的每个括号中都是等比数列,如果用求和公式,需要做除法,而$mod$运算的分配律并不适用于除法,所以我们要考虑转化。

    1.递归(分治法)

    把问题分成规模更小的同类子问题,然后递归求解

    设$sum(p,c)=1+p+p^2+…+p^c$

    若$c$为奇数,则

    $$sum(p,c)=(1+p+…+p^{frac{c-1}{2}})+(p^{frac{c+1}{2}}+…+p^c)$$

    $$=(1+p+…+p^{frac{c-1}{2}})+p^{frac{c+1}{2}}*(1+p+…+p^{frac{c-1}{2}})$$

    $$=(1+p^{frac{c+1}{2}})*sum(p,frac{c-1}{2})$$

    若$c$为偶数,则

    $$sum(p,c)=(1+p^{frac{c}{2}})*sum(p,frac{c}{2}-1)+p^c$$

    2.逆元法

    关于乘法逆元的知识详见数论专题学习笔记,这里只放一下代码了。

    【代码实现】

     1 #include<cstdio>
     2 #define rg register
     3 #define go(i,a,b) for(rg int i=a;i<=b;i++)
     4 #define ll long long
     5 using namespace std;
     6 int a,b,m,ans=1;
     7 const int mod=9901;
     8 int p[20],c[20];
     9 void divide(int x){//分解质因数
    10     m=0;
    11     for(rg int i=2;i*i<=x;i++){
    12         if(x%i==0){
    13             p[++m]=i,c[m]=0;
    14             while(x%i==0) x/=i,c[m]++;
    15         }
    16     }
    17     if(x>1) p[++m]=x,c[m]=1;
    18     return;
    19 }
    20 int ksm(int x,ll y){
    21     int as=1;
    22     while(y){
    23         if(y&1) as=(ll)as*x%mod;
    24         x=(ll)x*x%mod;
    25         y>>=1;
    26     }
    27     return as;
    28 }
    29 int main(){
    30     scanf("%d%d",&a,&b);
    31     divide(a);
    32     go(i,1,m){
    33         if((p[i]-1)%mod==0){//特判没有逆元的情况
    34             ans=((ll)b*c[i]+1)%mod*ans%mod;
    35             continue;
    36         }
    37         int x=ksm(p[i],(ll)b*c[i]+1);//分子
    38         x=(x-1+mod)%mod;
    39         int y=p[i]-1;//分母
    40         y=ksm(y,mod-2);//费马小定理求逆元
    41         ans=(ll)ans*x%mod*y%mod;
    42     }
    43     printf("%d
    ",ans);
    44     return 0;
    45 }
    逆元法
     1 #include<cstdio>
     2 #define rg register
     3 #define go(i,a,b) for(rg int i=a;i<=b;i++)
     4 #define ll long long
     5 using namespace std;
     6 int a,b,m,ans=1;
     7 const int mod=9901;
     8 int p[20],c[20];
     9 void divide(int x){//分解质因数
    10     m=0;
    11     for(rg int i=2;i*i<=x;i++){
    12         if(x%i==0){
    13             p[++m]=i,c[m]=0;
    14             while(x%i==0) x/=i,c[m]++;
    15         }
    16     }
    17     if(x>1) p[++m]=x,c[m]=1;
    18     return;
    19 }
    20 int ksm(int x,ll y){
    21     int as=1;
    22     while(y){
    23         if(y&1) as=(ll)as*x%mod;
    24         x=(ll)x*x%mod;
    25         y>>=1;
    26     }
    27     return as;
    28 }
    29 int sum(int x,int y){
    30     if(y==0) return 1;
    31     if(y==1) return x+1;
    32     if(y&1)    return (1+ksm(x,(y+1)/2))*sum(x,(y-1)/2)%mod;
    33     else return (1+ksm(x,y/2))*sum(x,y/2-1)%mod+ksm(x,y)%mod;
    34 }
    35 int main(){
    36     scanf("%d%d",&a,&b);
    37     if(a==0) {printf("0
    ");return 0;}//注意特判
    38     if(b==0) {printf("1
    ");return 0;}
    39     divide(a);
    40     go(i,1,m)
    41         ans=ans*sum(p[i],b*c[i])%mod;
    42     printf("%d
    ",ans);
    43     return 0;
    44 }
    递归法
  • 相关阅读:
    洛谷 1850 NOIP2016提高组 换教室
    2018牛客多校第三场 C.Shuffle Cards
    2018牛客多校第一场 B.Symmetric Matrix
    2018牛客多校第一场 A.Monotonic Matrix
    2018牛客多校第一场 D.Two Graphs
    2018宁夏邀请赛L Continuous Intervals
    2018宁夏邀请赛K Vertex Covers
    BZOJ
    HDU
    ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (ECPC 2015)
  • 原文地址:https://www.cnblogs.com/THWZF/p/11248143.html
Copyright © 2011-2022 走看看