洛谷P2398 GCD SUM [数论,欧拉筛]
GCD SUM
题目描述
for i=1 to n
for j=1 to n
sum+=gcd(i,j)
给出n求sum. gcd(x,y)表示x,y的最大公约数.
输入输出格式
输入格式:
n
输出格式:
sum
输入输出样例
说明
数据范围 30% n<=3000 60% 7000<=n<=7100 100% n<=100000
分析:
无聊的出题人出的无聊的数学题。
这里博主用了一种比较暴力的思想,直接枚举以$1\thicksim n$为$GCD$的数对个数,然后累加得到答案就行了,然后就不难得到公式:
$ans=\sum^n_{i=1}((\sum^{\lfloor n/i\rfloor}_{j=1} \phi(i)-1)*i+i)$
Code:
//It is made by HolseLee on 27th Oct 2018 //Luogu.org P2398 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const ll N=1e5+7; ll n,phi[N],sum[N],q[N],top,ans; bool vis[N]; void ready() { phi[1]=1; for(ll i=2; i<=n; ++i) { if( !vis[i] ) phi[q[++top]=i]=i-1; for(ll j=1,k; j<=top && (k=q[j]*i)<=n; ++j) { vis[k]=1; if( i%q[j] ) phi[k]=phi[i]*(q[j]-1); else { phi[k]=phi[i]*q[j]; break; } } } for(ll i=2; i<=n; ++i) sum[i]=sum[i-1]+phi[i]; } int main() { scanf("%lld",&n); ready(); ll now; for(ll i=1; i<=n; ++i) { now=n/i; //cout<<sum[now]<<' '<<i<<'\n'; ans+=sum[now]*i*2+i; } printf("%lld\n",ans); return 0; }
蒟蒻写博客不易,如果有误还请大佬们提出
如需转载,请署名作者并附上原文链接,蒟蒻非常感激
名称:HolseLee
博客地址:www.cnblogs.com/cytus
个人邮箱:1073133650@qq.com
如需转载,请署名作者并附上原文链接,蒟蒻非常感激
名称:HolseLee
博客地址:www.cnblogs.com/cytus
个人邮箱:1073133650@qq.com