P5106 dkw的lcm
阿新 • • 發佈:2018-12-18
終於A了……細節真多……
首先我們發現這是個連乘,而且\(\phi\)是個積性函式,所以我們可以考慮不同的質因子以及它的不同次數的貢獻。簡單來說就是把每一次的\(\phi(lcm(i_1,i_2,...))\)拆成一堆\(\phi(p^c)\)的乘積
如果列舉到的\(k\)個數裡質因子\(p\)的最大次數為\(c\),那麼最終的答案就要乘上一個\(\phi(p^c)\)。所以我們的目的就是要求出這\(k\)個數裡\(p\)的最大次數為\(c\)時的方案數\(t\),然後這部分對答案的貢獻就是\(\phi(p^c)^t\)
計算方案的部分可以用容斥解決。設\(d_p(i)\)表示質因子\(p\)
最後是\(s_p(i)\)怎麼計算。我們可以單獨考慮每一位的方案數最後\(k\)位乘起來就好了。先考慮質因子\(p\)的最高次數剛好為\(i\)的情況,對於某一位來說,能選的數\(j\)要滿足\(j\times p^i\leq n\)且\(j\)不包含\(p\)這個質因子,那麼滿足條件的\(j\)的次數就是\(\left\lfloor\frac{n}{p^i}\right\rfloor-\left\lfloor\frac{n}{p^{i+1}}\right\rfloor\)
然後注意一個細節,因為上面\(s_p\)和\(d_p\)的計算基本都是要炸精度所以要取模,然而因為這兩個東西是作為次數出現的,所以根據尤拉定理取模的時候要模\(\phi(P)\)而不是\(P\),因為這個東西調死掉……
然後就沒有然後了
//minamoto #include<bits/stdc++.h> #define R register #define ll long long #define inf 0x3f3f3f3f #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i) #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) using namespace std; const int N=2e6+5,P=1e9+7,Phi=P-1; int p[N],vis[N],phi[N],kkk[N];bool flag=0; int n,k,m,ans;ll sum,t; inline int add(R int x,R int y,R int P){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y,R int P){return x-y<0?x-y+P:x-y;} inline int ksm(R int x,R int y,R int P){ int res=1; for(;y;y>>=1,x=1ll*x*x%P)if(y&1)res=1ll*res*x%P; return res; } void init(int n){ phi[1]=kkk[1]=1; fp(i,2,n){ if(!vis[i])p[++m]=i,phi[i]=i-1,kkk[i]=ksm(i,k,Phi); //預處理一下phi和所有數的k次冪 for(R int j=1;j<=m&&1ll*i*p[j]<=n;++j){ vis[i*p[j]]=1,kkk[i*p[j]]=1ll*kkk[i]*kkk[p[j]]%Phi; if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];break;} phi[i*p[j]]=phi[i]*(p[j]-1); } } } void solve(int p){ sum=kkk[n-n/p]; for(R int i=p;i<=n;(1ll*i*p<=n?i*=p:i=inf)){ t=dec(kkk[n-n/(1ll*i*p)],sum,Phi); ans=1ll*ans*ksm(phi[i],t+Phi,P)%P, sum=add(sum,t,Phi); } } int main(){ // freopen("testdata.in","r",stdin); scanf("%d%d",&n,&k),ans=1,init(n);if(n==1)return puts("1"),0; fp(i,1,m)solve(p[i]);return printf("%d\n",ans),0; }