首页 > 代码库 > BZOJ 2190仪仗队【欧拉函数】
BZOJ 2190仪仗队【欧拉函数】
问题的唯一难点就是如何表示队长能看到的人数?如果建系,队长所在的点为(0,0)分析几组数据就一目了然了,如果队长能看到的点为(m,n),那么gcd(m,n)=1即m n 互质或者是(0,1),(1,0)两点。证明很简单,如果gcd(m,n)=d 那么(m/d,n/d)必然会挡住点(m,n),所以gcd(m,n)=1是必然的。这样问题就划归到2到n-1有多少数互质。由于欧拉函数的意义是小于n的与n互质的数的个数,所以知道欧拉函数意义的人都能第一时间想到答案就是t=φ(2)+φ(3)+…+φ(n-1) ,如果点(m,n)可以被看到,根据对称性(n,m)也可以被看到,再加上(1,1)(由于(1,1)是唯一不具有对称性的点所以分开来考虑)(0,1),(1,0)三点,所以答案 ans=t*2+3 ,如果定义φ(1)=1 那么答案就是φ(1)+φ(2)+φ(3)+…+φ(n-1)+1了
#include<iostream>
#include<cstdio>
#include <math.h>
using namespace std;
int prime[20000]={0},t;
bool isprime(int k)
{
for (int i=1;i<=t-1;i++)
{
if (k % prime[i]==0)return false;
}
return true;
}
int euler(int k)
{
intnow=1,e=1,i;
while(k!=1)
{
for(i=now;i<=t-1;i++)
{
now++;
if(k % prime[i]==0)break;
}
e=e*(prime[i]-1);k=k/prime[i];
while (k % prime[i]==0)
{
e=e*prime[i];
k=k/prime[i];
}
}
returne;
}
int main()
{
t=2;
int m,n,i,ans=0;
scanf("%d",&n);
prime[1]=2;
for (i=2;i<=40000;i++)
{
m=i*2-1;
if (isprime(m))
{
prime[t]=m;
t++;
}
}
for(i=1;i<=n-1;i++)
{
ans+=euler(i);
}
ans=ans*2+1;
printf("%d",ans);
return 0;
}
BZOJ 2190仪仗队【欧拉函数】