AcWing 201. 可见的点(欧拉函数)

文章目录

题意

就是站在原点(0, 0),在 0 ≤ x , y ≤ n 0 \le x, y \le n 0x,yn,你能直接看到的点有多少个点(x, y)。

思路

我们先把整张图按照对角线分成两个部分。对角线这条线上的我们先不考虑其实(就只有一个点会被看到)。我们只看其中的一部分:

ncnt
11
21+1
31+1+2
41+1+2+2
51+1+2+2+4

每一行最后一个数代表这一行有多少个点可以被看到。
通过发现我们可以知道每一行能被看到的书就是 ϕ ( i ) \phi(i) ϕ(i)
另一部分的个数其实是相同的。那么最后答案我们在加上对角线这个只有一个的点。

a n s = s u m ( n ) ∗ 2 + 1 ans = sum(n) * 2 + 1 ans=sum(n)2+1,sum代表的是前n个数的 ϕ ( i ) \phi(i) ϕ(i)的和也可以理解为前缀和。所以我们只有运用筛法把一千以内的所有数的欧拉函数给求出来,最后再求一遍前缀和就可以利用上述式子求出答案了。

代码

#include<bits/stdc++.h>

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define int long long 
#define endl "\n"
#define xx first
#define yy second

using namespace std;

const int N = 2e3 + 10;

int n, _;
int pr[N], cnt, phi[N], sum[N];
bool st[N];

void euller()
{
    phi[1] = 1;
    
    for(int i = 2; i < N; i ++)
    {
        if(!st[i])
        {
            pr[cnt++] = i;
            phi[i] = i-1;
        }
        
        for(int j = 0; pr[j]*i < N; j ++)
        {
            st[pr[j]*i] = 1;
            if(i % pr[j] == 0)
            {
                phi[i * pr[j]] = phi[i] * pr[j];
                break;
            }
            phi[i * pr[j]] = phi[i] * (pr[j] - 1);
        }
    }
    
    for(int i = 1; i < N; i ++)
    {
        sum[i] = sum[i-1] + phi[i];
    }
}

void solve(int id)
{
    cin >> n;
    cout << id << " " << n << " ";
    cout << sum[n] * 2 + 1 << endl;
}

signed main()
{
    IOS;
    euller();
    cin >> _;
    for(int i = 1; i <= _; i ++) solve(i);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值