题目描述
输入描述:
输出描述:
示例1
输入
3
输出
5
分析:
1.这个题其实考的是一个莫比乌斯反演题,但是由于我知识储备不够,没有看出来,题目给的范围可以瞎搞一下,所以下面容斥可以过。
2.转换一下就是一道经典的反演题,参考
AC代码:
容斥:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int M=1e5+10;
int f[M];
int cal(int x){
int num=0;
while(x){
num+=x%10;
x/=10;
}
return num;
}
int main(){
int n;
cin>>n;
ll ans=0;
for(int i=2;i<=n;i++){
int m=i,kk=0;
for(int j=2;j*j<=n;j++){///唯一分解定理,求其素因子
if(m%j==0){
f[kk++]=j;
while(m%j==0)
m/=j;
}
}
if(m>1) f[kk++]=m;
int lim=1<<kk,sum=0;
for(int j=1;j<lim;j++){///枚举哪些质因子被拿出来了
int x=j,su=0,sm=1;
for(int k=0;k<kk;k++){///找出哪些素因子被拿出
if(x&(1<<k)){
su++;
sm*=f[k];
}
}
if(su&1) sum+=n/sm-i/sm;///规定,当素因子拿出奇数个,则加上,在(i~n)里存在该质因子数的个数。
else sum-=n/sm-i/sm;///当为偶数时,此时之前已经拿出,重复,需减掉。
}
///sum为不互质的数;
///n-i,为总数,原为找寻的for(j=i+1,j<=n;j++)中(i,j)互质的数
ans+=(n-i-sum)*cal(i);
}
ans+=n;///没有枚举1,因为全部会被标记,所以+1
cout<<ans<<endl;
return 0;
}
莫比乌斯反演:
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int M=1e5+10;
int prime[M],mu[M],f[M];
int cnt;
bool book[M];
void sieve(int N)
{
mu[1]=1;
for(int i=2; i<=N; i++)
{
if(!book[i])
prime[cnt++]=i,mu[i]=-1;
for(int j=0; prime[j]<=N/i; j++)
{
book[i*prime[j]]=true;
if(i%prime[j]==0)
break;
mu[i*prime[j]]=-mu[i];
}
}
for(int i = 0; i <= N; i++)
{
int x = i;
while(x)
{
f[i]+=x%10;
x/=10;
}
}
}
int main()
{
sieve(M - 1);
int n;
scanf("%d",&n);
ll ans=0;
for(int i=1; i<=n; i++)
{
if(!mu[i])
continue;
ll res=0;
for(int j=1; j<=n/i; j++)
res+=(ll)f[j*i]*(n/i-j+1);//1LL,长整型1,和*1.0一样,改变数据类型用;
ans+=mu[i]*res;
}
printf("%lld\n",ans);
return 0;
}