题目:
f(n)=∑i=1n∑j=1i⌈ij⌉[(i,j)=1],
where [(i,j)=1] evaluates to be 1 if gcd(i,j)=1 , otherwise 0 .
思路:
令F[i]=i/1+i/2+...+i/i 向上取整
D[i]=i/1+i/2+...+i/i 向下取整
其中F[i]=D[i-1]+1,D[i]=F[i]-i+cnt,cnt为i的因子的个数
然后就可以使用容斥定理了。
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
// 0x3f3f3f3f
const int MOD=1e9+7;
const int maxn=1e6+50;
bool check[maxn];
int prime[maxn];
int mu[maxn],sum[maxn];
int F[maxn],D[maxn],ans[maxn];
void Moblus(int n){
mm(check,false);
mu[1]=1;
int tot=0;
for(int i=2;i<=n;i++){
if(!check[i]){
prime[tot++]=i;
mu[i]=-1;
}
for(int j=0;j<tot;j++){
if(i*prime[j]>n)
break;
check[i*prime[j]]=true;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else{
mu[i*prime[j]]=-mu[i];
}
}
}
F[1]=D[1]=1;
for(int i=2;i<=n;i++){
F[i]=D[i-1]+i;
int x=i,cnt=1;
for(int j=0;prime[j]*prime[j]<=i;j++){
int num=0;
while(x%prime[j]==0){
num++;
x/=prime[j];
}
cnt*=(num+1);
}
if(x>1) cnt*=2;
D[i]=F[i]-i+cnt;
}
for(int i=1;i<=n;i++) ans[i]=F[i];
for(int i=2;i<=n;i++){
for(int j=i;j<=n;j+=i)
ans[j]+=mu[i]*F[j/i];
}
for(int i=2;i<=n;i++){
ans[i]=(ans[i]+ans[i-1])%MOD;
}
}
int main(){
int n;
Moblus(maxn-5);
while(~scanf("%d",&n)){
printf("%d\n",ans[n]);
}
return 0;
}