2020江西省大学生程序设计竞赛题解

Simple Math Problem

  • 这个是一个数论题目,我们先将题目要求的式子进行转化
    ∑ i = 1 n ∑ j = 1 i [ g c d ( i , j ) = = 1 ] f [ j ] = ∑ i = 1 n ∑ j = 1 n f [ i ] [ g c d ( i , j ) = 1 ] − ∑ i = 1 n ∑ j = 1 i f [ i ] [ g c d ( i , j ) = 1 ] + f ( 1 ) \sum_{i=1}^n\sum_{j=1}^i[gcd(i,j)==1]f[j] \\ =\sum_{i=1}^n\sum_{j=1}^nf[i][gcd(i,j)=1]-\sum_{i=1}^n\sum_{j=1}^if[i][gcd(i,j)=1]+f(1) i=1nj=1i[gcd(i,j)==1]f[j]=i=1nj=1nf[i][gcd(i,j)=1]i=1nj=1if[i][gcd(i,j)=1]+f(1)

  • 这个式子可以这样理解,我们需要枚举从1-n的所有的数字,然后找到比这个数字i小的j,同时满足i和j互质,将f(j)的贡献累加到答案(也就是对于每对互质的元组,我们只计算小的那个数字的贡献)。其实就是先求出枚举1-n的所有的数字i,然后计算与i互质的数字的个数,将f(i)的每个贡献累加在一起。注意这里的互质的元组(i,j)不一定是i更大的,存在i>j和i<j的情况。求出这个之后,我们只需要减去从1-n进行枚举i,然后求出对于每个i,小于i的同时与i互质的数字的个数,然后累加f(i)的贡献。这样其实就是对于每个元组(i,j),这里的i是大于j的。减去之后剩下的就是对于每对互质的元组,这里的满足i<j,同时计算小的那个数字的贡献。这样不就是我们所求的吗?但是最后计算的时候发现总是会比正确的答案少1,这是因为(1,1)这个位置是特殊的,没有计算到,所以我们最后还要加上1就行了。

  • 计算的话,式子的前半部分利用莫比乌斯反演进行求解。后半部分就是一个欧拉函数求解即可。

  • 代码如下

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=100010;
ll f[N],phi[N],mu[N];
bool vis[N];
ll prime[N],g[N];
int m=0;
int n;
// 获取f数组 
int getsum(int x){
   
	int sum=0;
	while(x){
   
		sum+=(x%10);
		x/=10;
	}
	return sum;
}

// 得到莫比乌斯函数和欧拉函数 
void getmu(){
   
	phi[1]=1,mu[1]=1;
	for(int i=2;i<=n;i++){
   
		if(!vis[i]){
   
			mu[i]=-1;
			phi[i]=i-1;
			prime[++m]=i;
		}
		
		for(int j=1;j<=m&&(ll)i*prime[j]<=n;j++){
   
			vis[i*prime[j]]=true;
			if(i%prime[j]==0){
   
				phi[i*prime[j]]=phi[i]*prime[j];
				mu[i*prime[j]]=0;
				break;
			}
			phi[i*prime[j]]=phi[i]*(prime[j]-1);
			mu[i*prime[j]]=-mu[i];
		}
	}
	
	// 求一个前缀和,求每个数倍数的f数组的总和 
	for(int i=1;i<=n;i++){
   
		for(int j=i;j<=n;j+=i){
   
			g[i]+=f[j];
		}
	}
} 
int main(){
   
    memset(vis,false,sizeof(vis));
	cin>>n;
	for(int i=1;i<=n;i++){
   
		f[i]=getsum(i);
	}
	
	getmu();
	
	ll ans1=0,ans2=0;
	for(int i=1;i<=n;i++){
   
		ans1+=mu[i]*(n/i)*g[i];
		ans2+=f[i]*phi[i];
	
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值