「CF1208G」 Polygons

「CF1208G」 Polygons

似乎我校神犇在很久以前和我提过这题?

首先有一点显而易见:这 \(k\) 个多边形肯定至少有一个公共的顶点。假设我们将此点定义为起点。

那么对于一个正 \(n\) 边形,每一条边所截的短弧所对应的圆心角大小相等,所以我们可以把顶点标记为 \(\frac{1}{n},\frac{2}{n},\frac{3}{n},\cdots,\frac{n}{n}\)

那么有结论:对于任意一个正 \(n\) 边形的顶点,当且仅当顶点标号为一个最简分数时才会被统计进答案。

证明也很简单,假设存在一个正 \(n\) 边形顶点标号为非最简分数被统计进答案,那么将标号化为最简分数后其所对应的正多边形我们一定没有选择。但是显然这个正多边形的点数比我们刚才选择的正 \(n\) 边形要少,这与题目要求相悖,故假设不成立。

因为 \(n\ge 3\),所以有两个顶点没有被我们统计到:\(\frac{1}{2} , \frac{n}{n}\)

考虑特判:

  • \(k=1\) 时我们一定会选择正三角形,其包含 \(\frac{n}{n}\)

  • \(k=2\) 时我们可以选择正三角形和正四边形,其包含 \(\frac{1}{2} , \frac{n}{n}\)

  • \(k\ge 3\) 时由于已经选择了正三角形和正四边形,未统计的两个顶点已经统计,所以不受影响。

考虑对一个正 \(n\) 边形统计这样的最简分数,很显然可以发现答案就是 \(\varphi(n)\)。所以我们选择从 \(\varphi(5)\) 开始的前 \(k\) 大的欧拉函数值即可。

总时间复杂度为 \(O(n\log_2n)\),使用基数排序可优化至 \(O(n)\)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int p[maxn],pri[maxn],phi[maxn],cnt;
int n,k;
int init(){
	phi[1]=1;
	for(int i=2;i<=n;++i){
		if(!p[i]){
			pri[++cnt]=i,phi[i]=i-1;
		}
		for(int j=1;j<=cnt&&pri[j]*i<=n;++j){
			p[pri[j]*i]=1;
			if(i%pri[j]==0){
				phi[pri[j]*i]=phi[i]*pri[j];
				break;
			} 
			else phi[i*pri[j]]=phi[i]*(pri[j]-1);
		}
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>k;
	if(k==1) cout<<3<<'\n',exit(0);
	if(k==2) cout<<6<<'\n',exit(0);
	init();
	sort(phi+5,phi+n+1);
	long long ans=6;
	for(int i=5;i<=5+k-2-1;++i) ans+=phi[i];
	cout<<ans<<'\n';
	return 0;
}
posted @ 2020-09-10 20:12  Henry__Huang  阅读(105)  评论(0编辑  收藏  举报