题解 P2158 【[SDOI2008]仪仗队】
思路
这道题的具体做法楼上dalao已经讲的非常清楚了qwq
具体地,我们沿着对角线将这个正方形切开,得到两个直角三角形。
我们发现,实际上要求的答案大概就是在1到n的范围里不同的gcd(i,j)的个数,对于一个特定的i,gcd(i,j)的个数就是i-1的欧拉函数值。
那么我们就将这个问题转化成为了欧拉函数的版子题。
代码实现
我们使用筛法求euler函数,一次性计算完毕,能在0ms内跑完所有的测试点。
#include <bits/stdc++.h>
using namespace std;
int n,euler[400001];
void Euler(int Max){
Max=n-1;
euler[1]=1;
for(int i=2;i<=Max;i++)
euler[i]=i;
for(int i=2;i<=Max;i++)
if(euler[i]==i)
for(int j=i;j<=Max;j+=i)
euler[j]=euler[j]/i*(i-1);
}//上面是线性欧拉函数的版子
int main() {
scanf("%d",&n);
Euler(n);
int ans=0;
for (int i=1;i<=n-1;i++)
ans+=euler[i];
printf("%d",ans*2+1);//最后我们将答案×2,因为我们只计算了一个直角三角形,同时加上1,因为对角线方向依然能看到一个同学
return 0;
}