[SDOI2008]仪仗队(欧拉筛裸题)

题目描述

作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如右图)。  现在,C君希望你告诉他队伍整齐时能看到的学生人数。

输入输出格式

输入格式:

共一个数N

输出格式:

共一个数,即C君应看到的学生人数。

思路:

典型的欧拉筛

为了帮助萌新,我先从欧拉函数开讲

什么是欧拉函数?

定义:与一个数的约数有且只有1的数(互质)的个数(比如说2有1一个,6有1,5两个)

性质:积性函数(Phi(i)等于他的所有质因数的phi值的乘积)

为什么能这么做呢?

其实这道题求的是有多少种不同的斜率

为什么呢?

看图:

很显然,一个斜率上只能看到一个人,该斜率其他人都会被堵得死死的。。。

那么,每一个独立的斜率又如何表示呢?

我们用数对(x,y)表示斜率

我们知道,如果x,y不互质,那么他们可以同时除以他们的最大公约数(设为k),则该斜率可表示为(x/k,y/k)

很显然会有重复

所以为了避免重复,我们所求的是互质点对的个数

互质点对很显然就是欧拉函数

这里我用的是(nlogn)的算法——埃氏筛

从2开始,一个数i如果因数标记为1,则他是素数,他的欧拉函数值为i-1,同时,利用它来更新所有它的倍数的因数标记,如果因数标记大于1,则其不是素数,根据积性函数的性质,Phi[i]=其各因数的乘积,当其含有多次方因子时(比如8=2^3),那么Phi[i]的值为phi[2]*2*2;

不说了,代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
long long ll;
long long e[40010];
long long n,ans;
int main()
{
    ans=2;
    cin>>n;
    if(n==1)
    {
        cout<<0;
        return 0;
    }
    for(int i=1;i<=n;++i)
    {
        e[i]=i;
    }
    for(int i=2;i<=n;++i)
    {
        if(e[i]==i)
        {
            for(int j=i;j<=n;j+=i)
            {
                e[j]=e[j]/i*(i-1);
            }
        }
    }
    n--;
    for(int i=2;i<=n;++i)
    {
        ans+=e[i]*2;
    }
    cout<<ans+1;
}        

原文地址:https://www.cnblogs.com/ztz11/p/9059526.html

时间: 2024-10-08 21:05:59

[SDOI2008]仪仗队(欧拉筛裸题)的相关文章

【BZOJ 2190】【SDOI 2008】仪仗队 欧拉筛

欧拉筛模板题 #include<cstdio> using namespace std; const int N=40003; int num=0,prime[N],phi[N]; bool notp[N]; inline void shai(int n){ phi[1]=1; for(int i=2;i<=n;++i){ if (!notp[i]){ prime[++num]=i; phi[i]=i-1; } for(int j=1;j<=num&&i*prime

Goldbach&#39;s Conjecture POJ - 2262 线性欧拉筛水题 哥德巴赫猜想

题意 哥德巴赫猜想:任一大于2的数都可以分为两个质数之和 给一个n 分成两个质数之和 线行筛打表即可 可以拿一个数组当桶标记一下a[i]  i这个数是不是素数  在线性筛后面加个装桶循环即可 #include<cstdio> #include<cstring> using namespace std; bool Is_Primes[1000005]; int Primes[1000005]; int cnt; void Prime(int n){ cnt=0; memset(Is_

bzoj2190 [SDOI2008]仪仗队(欧拉函数)

2190: [SDOI2008]仪仗队 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 3203  Solved: 2062[Submit][Status][Discuss] Description 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图).    现在,C君希望你告诉他队伍整齐时能看到的学生人数.

2190: [SDOI2008]仪仗队(欧拉函数)

2190: [SDOI2008]仪仗队 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 3235  Solved: 2089 Description 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图).    现在,C君希望你告诉他队伍整齐时能看到的学生人数. Input 共一个数N. Output 共一个数

BZOJ 2190: [SDOI2008]仪仗队( 欧拉函数 )

假设C君为(0, 0), 则右上方为(n - 1, n - 1). 一个点(x, y) 能被看到的前提是gcd(x, y) = 1, 所以 answer = ∑ phi(i) * 2 + 2 - 1 = ∑phi(i) * 2 + 1 ( 1 <= i < n ). +2是因为(1, 0), (0, 1) 两个点, -1是因为(1, 1)重复计算了 -------------------------------------------------------------------------

POJ_2407 Relatives 【欧拉函数裸题】

一.题目 Given n, a positive integer, how many positive integers less than n are relatively prime to n? Two integers a and b are relatively prime if there are no integers x > 1, y > 0, z > 0 such that a = xy and b = xz. Input There are several test c

素数筛&amp;&amp;欧拉筛 BZOJ2818 Gcd BZOJ2190 [SDOI2008]仪仗队

折腾了一晚上很水的数论,整个人都萌萌哒 主要看了欧拉筛和素数筛的O(n)的算法 这个比那个一长串英文名的算法的优势在于没有多次计算一个数,也就是说一个数只筛了一次,主要是在%==0之后跳出实现的,具体的解释看的迷迷糊糊,特别是欧拉函数的求解 http://blog.csdn.net/lerenceray/article/details/12420725 代码如下 1 void ES(){ 2 for(int i=2;i<n;i++){ 3 if (!pd[i]){ 4 prime[++top]=

洛谷 P1865 A % B Problem (欧拉筛+前缀和)

题目背景 题目名称是吸引你点进来的 实际上该题还是很水的 题目描述 区间质数个数 输入输出格式 输入格式: 一行两个整数 询问次数n,范围m 接下来n行,每行两个整数 l,r 表示区间 输出格式: 对于每次询问输出个数 t,如l或r?[1,m]输出 Crossing the line 输入输出样例 输入样例#1: 2 5 1 3 2 6 输出样例#1: 2 Crossing the line 说明 [数据范围和约定] 对于20%的数据 1<=n<=10 1<=m<=10 对于100

常见模板(欧拉筛素数,最小生成树,快排,并查集,单源最短路)

欧拉筛素数: #include<cstdio> #define maxn 10000000+10 using namespace std; int n,prime[5000001],num_prime=0,m; bool if_prime[maxn]; void euler(int limit) { for(int i=2;i<=limit;i++) { if(!if_prime[i]) prime[++num_prime]=i; for(int j=1;prime[j]*i<=l