zoukankan      html  css  js  c++  java
  • [题解]CodeForces1208G Polygons

    CodeForces1208G Polygons

    What an interesting problem QuuuuQ...

    题目描述

    给出一个圆,找出k个边长在([3,n])范围内且互不相同的正多边形,通过旋转使得总的顶点个数最少。问最少的顶点个数

    (3 leq n leq 10^6,1 leq k leq n-2)

    Solution

    amazing~.

    首先,手模一下可以发现,假设我们选择了边长为(l) 的正多边形,那么,选择所有边长为(l)的因数的正多边形一定只会更优,因为在这种情况下不会增加点的个数

    然后,所有多边形至少有一个公共点,显然,记这个点为P

    那么,假设圆的周长为1,记圆上每一个点的位置为顺时针方向距离P的距离

    对于一个正(l)边形,它的顶点就是(0,frac{1}{l},frac{2}{l},...,frac{l-1}{l}),最终的答案就是不同的最简分数的个数。而对于l,如果分母和分子不互质,那么变成最简分数后分母就是(l)的一个因子(x),这个点已经被正(x)变形算过了,所以对于(l),新增的点的个数就是(phi (l)).

    注意没有2边形,所以需要特判


    关于欧拉函数(phi)

    (phi (x)=x*prod_{i=1}^{n} 1-frac{1}{p_i}),其中,p是x的质因数

    可以利用埃式筛法求欧拉函数

    void INIT(){
    	int cnt=0;
    	a[1].val=a[1].num=1;
    	rep(i,2,n){
    		a[i].num=i;
    		if(!vis[i])p[++cnt]=i,a[i].val=i-1;
    		for(int j=1;j<=cnt&&p[j]<=n/i;j++){
    			vis[i*p[j]]=1;
    			if(i%p[j]==0){a[i*p[j]].val=a[i].val*p[j];continue;}
    			a[i*p[j]].val=a[i].val*(p[j]-1);
    		}
    	}
    }
    

    Code

    #include<bits/stdc++.h>
    #define rep(X,A,B) for(int X=A;X<=B;X++)
    #define tep(X,A,B) for(int X=A;X>=B;X--)
    #define LL long long
    const int N=1000010;
    const int M=2100010;
    using namespace std;
    
    int n,k,f[N],vis[N],p[N];
    
    struct nn{
    	int val,num;
    }a[N];
    
    int cmp(nn A,nn B){
    	if(A.val==B.val)return (A.num&1)>(B.num&1);
    	return A.val<B.val;
    }
    
    void INIT(){
    	int cnt=0;
    	a[1].val=a[1].num=1;
    	rep(i,2,n){
    		a[i].num=i;
    		if(!vis[i])p[++cnt]=i,a[i].val=i-1;
    		for(int j=1;j<=cnt&&p[j]<=n/i;j++){
    			vis[i*p[j]]=1;
    			if(i%p[j]==0){a[i*p[j]].val=a[i].val*p[j];continue;}
    			a[i*p[j]].val=a[i].val*(p[j]-1);
    		}
    	}
    }
    
    void SOLVE(){
    	LL ans=0;
    	int flg=0;
    	sort(a+1,a+n+1,cmp);
    	rep(i,3,k+2){
    		//printf("a[%d]=%d %d
    ",i,a[i].val,a[i].num);
    		ans+=1LL*a[i].val;
    		if(a[i].num%2==0)flg=1;
    	}
    	printf("%lld
    ",ans+flg+1);
    }
    
    int main(){
    	scanf("%d%d",&n,&k);
    	INIT();
    	SOLVE();
    	return 0;
    }
    
  • 相关阅读:
    x01.Weiqi.6: 立体棋子
    x01.Game.MapEditor: 地图编辑器
    SQL Server插入中文出现乱码??的解决办法
    Cachecontrol使用:header('Cachecontrol:private')
    验证身份证号码Javascript代码
    .Net GDI+缩放绘图
    Access(JETSQL)问题集锦
    Android开发中Google谷歌地图坐标系怎么转Baidu百度地图坐标系
    21、桥接模式(Bridge模式)详解
    22、装饰模式(装饰设计模式)详解
  • 原文地址:https://www.cnblogs.com/SCL123/p/11599916.html
Copyright © 2011-2022 走看看