UVA 11426

欧拉函数+GCD

题目大意 求下面这个

\sum_{i=1}^{i<N}\sum_{j=i+1}^{j<N}GCD(i,j)

看了很多blog···感觉都讲的很不清楚(看不懂),肯定是我太弱了。

所以我决定自己写一篇,然后看看能不能在写的过程中弄清楚。

因为脑子可能没别人好用,看文字很难看出个所以然,所以我学习一般都需要例子来加以理解,我也认为这样可以让人更加清晰的理解我想表达什么。

如果有错误,不吝请教。

然后考虑一下数据范围···暴利绝对T的。

然后开始分析题目

既然不能暴利,那么能不能换一种思路?

假设f[n]=gcd(1,n)+gcd(2,n)+...gcd(n-1,n);

那么我们要求的ans[n]=f(2)+f(3)+f(4)+...+f(n);

所以我们只要把f[n]求出来就好了。

对gcd(x,n)进行分类,用a[i]表示gcd(x,n)=i的x的个数,意思就是从1~n-1中有多少个x0和x一样是gcd(x0,n)=i。

F[n]=\sum _{i=1}^{m}a[i]*i; 这里的m表示i的种类数目,没有别的含义。

举个例子F[6]=gcd(1,6)+gcd(2,6)+gcd(3,6)+gcd(4,6)+gcd(5,6);

但是这四个我们可以给他分类

不难发现gcd(1,6)==gcd(5,6)=1; //i=1的个数为欧拉函数φ(6);

gcd(2,6)==gcd(4,6)=2\rightarrowgcd(1,3)=1,gcd(2,3)=1;//此处i=2的个数也就是欧拉函数φ(3)

gcd(3,6)=3\rightarrowgcd(1,2)=1;//此处i=3的个数也就是欧拉函数φ(2);

然后利用数目乘以最后的i

F[6]=2*1+2*2+3*1=2+4+3=9;

那么gcd(x,n)=i,可以化简成gcd(x/i,n/i)=1.与n/i互质的个数也就是欧拉函数值φ(n/i);

通过欧拉函数找到了个数,那么这个公式不就出来了吗?

F[n]=i*\varphi [n/i]    i 表示这一类的权值,φ(n/i)则表示这一类的个数

所以最终的答案

ans[n]=ans[n-1]+F[n];

 

题目链接:https://cn.vjudge.net/problem/UVA-11426 

AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define fin(a,n) for(int i=a;i<=n;i++)
#define fjn(a,n) for(int j=a;j<=n;j++)
#define fni(n,a) for(int i=n;i>=a;i--)
#define fnj(n,a) for(int j=n;j>=a;j--)
const int maxn=4e6+10;
bool vis[maxn];
int prime[maxn];
ll f[maxn];
int phi[maxn];
ll ans[maxn];
int cnt=0;
void euler()//欧拉筛欧拉函数
{   phi[1]=1;//注意,欧拉函数1要单独判断
	memset(vis,true,sizeof(vis));
	vis[1]=false;
	fin(2,maxn)
	{
		if(vis[i])
		{
			prime[++cnt]=i;
			phi[i]=i-1;//欧拉函数特性一
		}
		for(int j=1;j<=cnt&&prime[j]*i<=maxn;j++)
		{
			vis[i*prime[j]]=false;
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];//欧拉函数是可积函数,特性二
				break;
			}
			phi[i*prime[j]]=phi[i]*phi[prime[j]];//欧拉函数特性三
		}
	}
}
int main()
{   ll n;
	euler();
	fin(1,maxn)
	{
		for(int j=i+i;j<=maxn;j+=i)
		f[j]+=i*phi[j/i];//找出F[n]
	}
	fin(1,maxn)ans[i]=ans[i-1]+f[i];//打表答案
	while(~scanf("%lld",&n))
	{   if(n==0)break;
		printf("%lld\n",ans[n]);
	}
	return 0;
 } 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值