题解 P2158 [SDOI2008]仪仗队

Link

P2158 [SDOI2008]仪仗队

Solve

通过观察发现,可以被看到的人必须满足(gcd(x,y)=1)证明也很简单,如果(x,y)不互质的话,那么一定会有((x/gcd(x,y),y/gcd(x,y)))((x,y))挡住,换句话说,如果(gcd(x,y))等于1,那么它一定可以把所有的((kx,ky))都挡住,所以我们只需要求出与(x,y)互质对的对数即可。

我们自然而然就想到了欧拉函数

介于这张图是对称的,所以只要统计下三角的数量最后( imes2)就是最后的答案,第一行第一列和((2,2))要特判

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=40005;
int N;
typedef long long LL;
int p[maxn],ans;
inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}
int main(){
	freopen("P2158.in","r",stdin);
	freopen("P2158.out","w",stdout);
	N=read();
	if(N==1){printf("0
");return 0;}
	for(int i=1;i<=N;i++)p[i]=i;
	for(int i=2;i<=N;i++){
		if(p[i]==i){
			for(int j=i;j<=N;j+=i){
				p[j]=p[j]/i*(i-1);
			}
		}
	}
	for(int i=2;i<N;i++){
		ans+=p[i]*2;
	}
	printf("%d
",ans+3);
	return 0;
}

同时也看到了一种莫比乌斯环的解法,至今没搞懂

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define debug printf("Now is Line : %d
",__LINE__)
#define file(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
#define mod 1000000007
il int read()
{
    re int x=0,f=1;re char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
    return x*f;
}
#define maxn 40000
int mu[maxn+5],prim[maxn+5],vis[maxn+5],cnt,n,ans;
signed main()
{
	n=read()-1;
	if(!n) return puts("0"),0;
    mu[1]=1;
    for(re int i=2;i<=n;++i)
    {
        if(!vis[i]) prim[++cnt]=i,mu[i]=-1;
        for(re int j=1;j<=cnt;++j)
        {
            if(prim[j]*i>n) break;
            vis[prim[j]*i]=1;
            if(i%prim[j]==0) break;
            mu[i*prim[j]]=-mu[i];
        }
    }	
	for(re int i=1;i<=n;++i) mu[i]+=mu[i-1];
	for(re int l=1,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		ans+=(mu[r]-mu[l-1])*(n/l)*(n/r);
	}
	printf("%d",ans+2);
    return 0;
}
原文地址:https://www.cnblogs.com/martian148/p/13541442.html