正题
首先要解出F(n)F(n)F(n),这东西也是问老Win才会的,不过会了也没什么用。
然后剩下的就是个求111到n!n!n! 与n!n!n!的gcd之和。∑i=1mgcd(i,m)∑d∣md∑i=1md[gcd(i,md)=1]∑d∣md∑g=1mdμ(g)mdg∑T∣m(id∗μ)(T)mT(φ∗id)(m)
\\ \sum_{i=1}^mgcd(i,m)
\\ \sum_{d|m} d\sum_{i=1}^{\frac{m}{d}} [gcd(i,\frac{m}{d})=1]
\\ \sum_{d|m} d\sum_{g=1}^{\frac{m}{d}}\mu(g) \frac{m}{dg}
\\ \sum_{T|m} (id*\mu)(T) \frac{m}{T}
\\ (\varphi * id)(m)
i=1∑mgcd(i,m)d∣m∑di=1∑dm[gcd(i,dm)=1]d∣m∑dg=1∑dmμ(g)dgmT∣m∑(id∗μ)(T)Tm(φ∗id)(m)
这个(φ∗id)(\varphi * id)(φ∗id)是两个积性函数的卷积,显然也是个积性函数。而且(φ∗id)(pk)(\varphi * id)(p^k)(φ∗id)(pk)很好求,然后把质因子个数筛出来就可以了。
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int T,n;
bool vis[N];
int p[N];
const int mod=1000000007;
int ksm(int x,int t){
int tot=1;
while(t){
if(t&1) tot=1ll*tot*x%mod;
x=1ll*x*x%mod;
t/=2;
}
return tot;
}
int main(){
scanf("%d",&T);
n=100005;
for(int i=2;i<=n;i++){
if(!vis[i]) p[++p[0]]=i;
for(int j=1;j<=p[0] && 1ll*i*p[j]<=n;j++){
vis[i*p[j]]=true;
if(i%p[j]==0) break;
}
}
for(int op=1;op<=T;op++){
scanf("%d",&n);
int ans=1;
for(int i=1;p[i]<=n;i++) {
int tot=0,tmp=n/p[i];
while(tmp) tot+=tmp,tmp/=p[i];
if(p[i]==2) tot--;
ans=1ll*ans*(1ll*(tot+1)*ksm(p[i],tot)%mod+mod-1ll*tot*ksm(p[i],tot-1)%mod)%mod;
}
printf("Case #%d: %d\n",op,ans);
}
}
本文介绍了一种求解从1到n!的整数与n!的最大公约数之和的方法。该算法利用了数学上的卷积性质,并通过质因数分解和快速幂运算等手段进行优化。
323

被折叠的 条评论
为什么被折叠?



