Link.
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;
}