您的位置:首页 > 其它

bzoj 2190: [SDOI2008]仪仗队

2016-05-10 20:55 471 查看

2190: [SDOI2008]仪仗队

Description

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

  现在,C君希望你告诉他队伍整齐时能看到的学生人数。

Input

  共一个数N。

Output

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

Sample Input

  4

Sample Output

  9

HINT

【数据规模和约定】   

对于 100% 的数据,1 ≤ N ≤ 40000

题解:

n^2的枚举应该是很好写的,先把所有的点都连线,枚举点的坐标,判断gcd(i,j)的值,若大于1即表示中间有点在连线之间

#include<stdio.h>
#include<iostream>
using namespace std;
int n,i,j,ans;
int gcd(int a,int b)
{
if(b==0) return a;
if(a%b==0) return b;else gcd(b,a%b);
}
int main()
{
scanf("%d",&n);
ans=n*n-1;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i!=0||j!=0)
{
if(gcd(i,j)-1) ans--;
}
cout<<ans;
return 0;
}


首先j可以只枚举小于等于i的部分,再乘2(注意i==j的情况)

那么对于当前i的答案就是总数减去与i互质的个数(用欧拉函数)

#include<stdio.h>
#include<iostream>
#include<math.h>
using namespace std;
int n,i,j,k,ans,sum,p[40005],a[40004];
int gcd(int a,int b)
{
if(b==0) return a;
if(a%b==0) return b;else gcd(b,a%b);
}
int main()
{
scanf("%d",&n);
p[1]=1;
for(i=2;i<=n;i++)
if(p[i]==0)
for(j=2;j<=n/i;j++)
p[i*j]=1;
ans=n*n-1;
for(i=2;i<n;i++)
{
k=0;
for(j=1;j<=(int)(sqrt(i));j++)
if(i%j==0)
{
if(p[j]==0)
{
k++;
a[k]=j;
}
if(i/j!=j&&p[i/j]==0)
{
k++;
a[k]=i/j;
}
}
sum=i;
for(j=1;j<=k;j++)
sum=sum*(a[j]-1)/a[j];
sum=i-sum;
ans-=sum*2+1;
}
cout<<ans;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: