题意:
给定 \(k\),求一个最小的 \(n\) 使得有恰好 \(k\) 个 \(i\in [1,n]\),满足对于所有 \(j\in [1,n]\),都有 \(x\) 满足 \(ix=j\mod n\) 并且 \(ix\le n^2\)。里面所有数都是正整数。
Sol:
我们考虑 \(\gcd(x,n)>1\) 的 \(x\)。因为 \(\gcd(x,n)>1\),所以 \(\operatorname{lcm}(x,n)<n^2\),设为 \(xt\)。因为 \(t<n\),所以 \(x\) 的 \(1\sim t\) 倍最多不会有超过 \(t\) 个不同的剩余类。但是 \(t+1\) 倍的 \(x\) 又和 \(1\) 倍的 \(x\) 本质相同,构成了循环,所以\(\gcd(x,n)>1\) 的 \(x\) 不行。因此 \(\gcd(x,n)=1\) 可以。而我们知道 \(\sum_{x=1}^n [\gcd(x,n)=1]=k\),所以这个题转化成求 \(\varphi(n)=k\) 的最小 \(n\)。
插播:\(\varphi(n)\) 是什么?
欧拉函数 \(\varphi(n)\) 为 \(1\sim n\) 种和 \(n\) 互素的元素个数。\(\varphi(n)\) 是积性函数。
\(\varphi(n)\) 的显性公式:\(\varphi(p)=p-1,\varphi(p^k)=p^k-p^{k-1}\)。
\[\begin{aligned} \varphi(n)=&\varphi(p_1^{a_1})\cdots \varphi(p_t^{a_t})\\=&(p_1^{a_1}-p_1^{a_1-1})\cdots (p_t^{a_t}-p_{t}^{a_t-1})\\=&p_1^{a_1}(1-\frac{1}{p_1})\cdots p_t^{a_t}(1-\frac{1}{p_t})\\=&n(1-\frac{1}{p_1})\cdots (1-\frac{1}{p_t})\\=&n\prod(1-\frac{1}{p}) \end{aligned} \]
因此
\[\begin{aligned} \varphi(n)=&n\prod(1-\frac{1}{p})\\ =&p_1^{a_1}\cdots p_t^{a_t}\prod_i \frac{p_i-1}{p_i}\\ =&p_1^{a_1-1}\cdots p_t^{a_t-1}\prod_i (p_i-1)\\ =&\prod_i p_i^{a_i-1}(p_i-1) \end{aligned} \]所以因为 \(\varphi(n)=k\),所以 \(p_i-1\mid k\)。
我们可以预处理 \(\sqrt{k}\) 以内的质数,\(\sqrt{k}\) 以外的指数单独判。每一次看要不要加上一个质数,前提条件是 \(p_i-1\mid k\)。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5+5;
const int M = 50000;
const ll inf = 2e12;
int lim,pr[N],vis[N],cnt;
void init(){
for (int i=2; i<=M; i++){
if (!vis[i]){
pr[++cnt]=i;
}
for (int j=1; j<=cnt && i*pr[j]<=M; j++){
vis[i*pr[j]]=1;
if (i%pr[j]==0){
break;
}
}
}
}
bool isp(ll x){
for (ll i=2; i*i<=x; i++){
if (x%i==0){
return 0;
}
}
return 1;
}
ll ans=inf;
void dfs(int p,int r,ll c){
if (c>=ans){
return;
}
if (r==1){
ans=c;
return;
}
if (r>lim && isp(r+1)){
ans=min(ans,c*(r+1));
}
for (int i=p+1; pr[i]-1<=min(lim,r); i++){
if (r%(pr[i]-1)==0){
int nr=r/(pr[i]-1);
ll nc=c*pr[i];
dfs(i,nr,nc);
while (nr%pr[i]==0){
nr/=pr[i];
nc*=pr[i];
dfs(i,nr,nc);
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
init();
int k;
cin>>k;
lim=sqrt(k+1);
dfs(0,k,1);
if (ans==inf){
cout<<0<<"\n";
}
else{
cout<<ans<<"\n";
}
return 0;
}
其实我也不知道复杂度是啥。但是在 \(k\le 2\cdot 10^9\) 跑过了。
标签:phi,prod,frac,int,varphi,cdots,ans,1673,timus From: https://www.cnblogs.com/SFlyer/p/18237461