CF1208G Polygons 题解

Codeforces
Luogu

Description.

在圆上选择最少的点,连线,使得可以连处 \(k\) 个边数不超过 \(n\) 的不同的正多边形。

Solution.

如果只有一个正多边形,相当于是 \(\frac 1n,\frac 2n,\cdots,\frac nn\) 这些位置有 \(1\)
我们如果从 \(n\) 小到大逐一选,那每个位置新增的贡献是多少。
\(\varphi(n)\),因为如果 \(\frac xn\) 不是既约分数,之前就统计过了。

如果按照 \(\varphi(n)\) 排序一个一个选,这样肯定最优了。

然后特判一下 \(\frac 12\)\(\frac 11\)

Coding.

点击查看代码
//Coded by leap_frog on 2021.11.19 {{{
//是啊……你就是那只鬼了……所以被你碰到以后,就轮到我变成鬼了
#include<bits/stdc++.h>
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
const int N=1000005;int n,k,a[N],f[N],g[N];
const int V=N;int pr[V],pc,ls[V],ph[V],mu[V];char pv[V];//prinit{{{
inline void prinit(int n=V-1)
{
	pv[1]=mu[1]=ph[1]=1,ls[1]=0;for(int i=1;i<=n;i++)
	{
		if(!pv[i]) pr[++pc]=i,mu[i]=-1,ph[i]=i-1,ls[i]=i;
		for(int j=1;j<=pc&&i*pr[j]<=n;j++)
		{
			ls[i*pr[j]]=pr[j],mu[i*pr[j]]=i%pr[j]?-mu[i]:0;
			ph[i*pr[j]]=ph[i]*(pr[j]-!!(i%pr[j]));
			pv[i*pr[j]]=1;if(i%pr[j]==0) break;
		}
	}
}//}}}
int main()
{
	read(n,k),prinit(n);ll rs=2;
	sort(ph+3,ph+n+1);for(int i=3;i<=k+2;i++) rs+=ph[i];
	return printf("%lld\n",rs),0;
}
原文地址:https://www.cnblogs.com/pealfrog/p/15575602.html