【NOIP2017模拟】春思

Description

这里写图片描述

Data Constraint

【NOIP2017模拟】春思_第1张图片

Solution

首先可以先把A分解质因数,依照正常的套路一般都是在质因数上做文章。我们先想一想求某一个数的因数个数的方法,大概就是各质数组合而得,这题的想法也类似,想办法把个个质数组合在一起。可以发现,如果把不同的质数分开计算就不会出现重复的情况,同时因为题目求的是因数的和,那我们就可以把某一个质数的答案直接加起来,因为计算满足分配率。当前某一个质数的贡献为 x1+x2+......+xn ,n为分解的x的个数,再乘上之前的质数的贡献就是当前质数对答案的贡献,用个等比数列求和就可以了。

Code

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int MO=9901,N=1e6+4;
#define fo(i,a,b) for(i=a;i<=b;i++)
struct arr{ll x,y;}a[N];
ll A,B,s[N],tot,num,sgm,ans;
int i,j,sum;
bool P[N];
void deal(int mx){
    fo(i,2,mx){
        if(!P[i]){s[++s[0]]=i,P[i]=1;}
        fo(j,1,s[0]){
            if(i*s[j]>mx) break;
            P[i*s[j]]=1;
            if(!(i%s[j])) break;
        }
    }
}
ll ksm(ll x,ll y){
    ll z=1;for(;y;y/=2,x=x*x%MO)if(y&1)z=z*x%MO;
    return z;
}
void calc(ll x,ll y){
    num=(ksm(x,y+1)-1+MO)%MO*ksm(x-1,MO-2)%MO;
    num=(num-1+MO)%MO;
}
int main(){
    scanf("%lld%lld",&A,&B);
    deal(sqrt(A));
    tot=A;
    fo(i,1,s[0]){
        if(!(tot%s[i])) a[++sum]=(arr){s[i]%MO,0};
        while(!(tot%s[i])){
            a[sum].y++;
            tot/=s[i];
        }
    }
    if(tot>1) a[++sum]=(arr){tot%MO,1};
    fo(i,1,sum) a[i].y*=B;
    ans=1;sgm=0;
    fo(i,1,sum){
        calc(a[i].x,a[i].y);
        ans=(ans+sgm*num%MO)%MO;
        sgm=(sgm+num+sgm*num%MO)%MO;
        ans=(ans+num)%MO;
    }
    printf("%lld\n",ans);
}

你可能感兴趣的:(NOIP)