1. 程式人生 > >【NOIP2017模擬】春思

【NOIP2017模擬】春思

Description

這裡寫圖片描述

Data Constraint

這裡寫圖片描述

Solution

首先可以先把A分解質因數,依照正常的套路一般都是在質因數上做文章。我們先想一想求某一個數的因數個數的方法,大概就是各質數組合而得,這題的想法也類似,想辦法把個個質數組合在一起。可以發現,如果把不同的質數分開計算就不會出現重複的情況,同時因為題目求的是因數的和,那我們就可以把某一個質數的答案直接加起來,因為計算滿足分配率。當前某一個質數的貢獻為x1+x2+......+xn,n為分解的x的個數,再乘上之前的質數的貢獻就是當前質數對答案的貢獻,用個等比數列求和就可以了。

Code

#include<iostream>
#include<algorithm> #include<math.h> #include<stdio.h> #include<string.h> 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); }