GCD2[caioj1281]\[BZOJ2818]莫反

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

caioj
BZOJ

思路

这是一道不用莫函的莫反(伪)题啊。

我们观察一下,

1 ≤ x , y ≤ n , gcd ⁡ ( x , y ) = p , p 是 质 数 1\le x,y\le n,\gcd(x,y)=p,p是质数 1x,yn,gcd(x,y)=p,p

可以转化为:

1 ≤ x , y ≤ n / p , gcd ⁡ ( x , y ) = 1 , 也 就 是 x , y 互 质 1\le x,y\le n/p,\gcd(x,y)=1,也就是x,y互质 1x,yn/p,gcd(x,y)=1x,y

那么我们先考虑 y ≥ x y\ge x yx的情况

y = x y=x y=x时,只有在 y = 1 , x = 1 y=1,x=1 y=1,x=1时, gcd ⁡ ( x , y ) = 1 \gcd(x,y)=1 gcd(x,y)=1成立。

y > x y>x y>x时,恰好 ∀ y ∈ [ 2 , n / p ] , ∀ x ∈ [ 1 , y ) \forall y\in[2,n/p],\forall x\in[1,y) y[2,n/p],x[1,y),与y互质的 x x x,共有 φ ( y ) \varphi(y) φ(y)个。

通俗地说,就是对于每一个 y y y,都会有 φ ( y ) \varphi(y) φ(y)个数与它互质。

对于每一个质数 p p p,当 y ≥ x , y ∈ [ 1 , n / p ] y\ge x,y\in[1,n/p] yx,y[1,n/p]时, a n s = ( ∑ i = 2 n / p φ ( i ) ) + 1 = ∑ i = 1 n / p φ ( i ) ans=(\sum_{i=2}^{n/p}\varphi(i))+1=\sum_{i=1}^{n/p}\varphi(i) ans=(i=2n/pφ(i))+1=i=1n/pφ(i)

那么 x , y x,y x,y没有大小关系时, a n s = ( ∑ i = 1 n / p φ ( i ) ∗ 2 ) − 1 ans=(\sum_{i=1}^{n/p}\varphi(i)*2)-1 ans=(i=1n/pφ(i)2)1,首先 ∗ 2 *2 2是因为, ( 2 , 3 ) , ( 3 , 2 ) (2,3),(3,2) (2,3),(3,2)是两对不同的二元组, − 1 -1 1是因为 y = x = 1 y=x=1 y=x=1,即 ( 1 , 1 ) (1,1) (1,1)的情况被选了两遍,要减去 1 1 1

那么对于 ∀ 质 数 p ∈ [ 1 , n ] \forall 质数p\in[1,n] p[1,n],都有 ( ∑ i = 1 n / p φ ( i ) ∗ 2 ) − 1 (\sum_{i=1}^{n/p}\varphi(i)*2)-1 (i=1n/pφ(i)2)1

则最终答案为:

∑ p 是 质 数 n ( ∑ i = 1 n / p ( φ ( i ) ∗ 2 ) − 1 ) \sum_{p是质数}^n(\sum_{i=1}^{n/p}(\varphi(i)*2)-1) pn(i=1n/p(φ(i)2)1)

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define ll long long
using namespace std;
const int N=1e7+10;
const int M=1e6+10;
int prime[M],m,n;ll phi[N];bool v[N];
inline void g_p()
{
    m=0;phi[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!v[i])prime[++m]=i,phi[i]=i-1;
        for(int j=1;j<=m&&i*prime[j]<=n;j++)
        {
            v[i*prime[j]]=1;
            if(i%prime[j]==0){phi[i*prime[j]]=prime[j]*phi[i];break;}
            else phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    for(int i=2;i<=n/2;i++)phi[i]+=phi[i-1];
}
int main()
{
    scanf("%d",&n);
    g_p();
    ll ans=0;
    for(int i=1;i<=m;i++)
        ans+=phi[n/prime[i]]*2-1;//1,1
    printf("%lld\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值