zoukankan      html  css  js  c++  java
  • 「CF1208G」 Polygons

    「CF1208G」 Polygons

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

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

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

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

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

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

    考虑特判:

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

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

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

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

    总时间复杂度为 (O(nlog_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<<'
    ',exit(0);
    	if(k==2) cout<<6<<'
    ',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<<'
    ';
    	return 0;
    }
    
  • 相关阅读:
    IO和序列化
    委托与事件
    [基础不过关填坑] 跨iframe触发事件
    有哪些新手程序员不知道的小技巧?
    给echarts加个“全屏展示”
    bootstrapTable使用场景及方式
    bootstrap datetimepicker 格式化yyyymmdd时,无法读取yyyymmdd格式
    【变态需求】bootstrapTable列排序-选择正序倒序不排序
    myeclipse、maven、tomcat、jdk技巧和坑【待完善】
    【调试技巧】 Fiddler高级用法之url映射请求
  • 原文地址:https://www.cnblogs.com/HenryHuang-Never-Settle/p/solution-CF1208G.html
Copyright © 2011-2022 走看看