bzoj2190仪仗队题解

Description

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

Input

  共一个数N。

Output

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


终于A了!这个欧拉函数搞得我头昏脑涨!!

简介(欧拉函数的值 )通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn为x的所有质因数,x是不为0的整数。φ(1)=1(唯一和1互质的数(小于等于1)就是1本身)。 (注意:每种质因数只一个。比如12=2*2*3


那么φ(12)=12*(1-1/2)*(1-1/3)=4)

经过观察发现这个仪仗队是对称的,我们可以求出左下角那一面;

再仔细观察,若(x,y)是可以看见的点,那么他们满足gcd(x,y)=1。

这时候,欧拉函数有用武之地啦!问题转化为:给定N,有数对(i,j),满足i>j,2<i<=n,2<=j<n,且gcd(i,j)=1,求数对的个数。(当然,结果要乘2,加1)我们枚举i(3-N),再枚举i的所有质因子k,用欧拉函数求出j的个数。

代码:

#include<stdio.h>
#include<cmath>
using namespace std;
long zhi[40001],n,cnt,i,j;
double ans;
long long max;
bool ok(long k)                      //判断质数
{
  for (long i=2;i<=trunc(sqrt(k));i++)
    if (k%i==0) return false;
  return true;
}
int main()
{
  scanf("%ld",&n);n--;              //N是人数个数,而边数要减1.
  zhi[1]=2;cnt=1;
  for (i=3;i<=n;i++) 
    if (ok(i)) zhi[++cnt]=i;       //预处理质数表
  for (i=1;i<=n;i++)
  {
    ans=i;
    for (j=1;j<=cnt;j++)
      if (i%zhi[j]==0) ans=ans*(zhi[j]-1)/zhi[j];     //欧拉函数
    max+=ans;
  }
  if (n<=0) printf("0");                               //特判0,1情况
  else printf("%ld",max*2+1);
  //scanf("%ld",&n);
  return 0;
}

你可能感兴趣的:(题解,数学,bzoj)