Admission to Exam欧拉函数逆运算

来源:互联网 发布:linux find mmin 编辑:程序博客网 时间:2024/05/16 00:31

Admission to Exam

At the end of the previous semester the students of the Department of Mathematics and Mechanics of the Yekaterinozavodsk State University had to take an exam in network technologies. N professors discussed the curriculum and decided that there would be exactly N2 labs, the first professor would hold labs with numbers 1, N + 1, 2N + 1, …, N2 − N + 1, the second one — labs with numbers 2, N + 2, 2N + 2, …, N2 − N + 2, etc. N-th professor would hold labs with numbers N, 2N, 3N, …, N2. The professors remembered that during the last years lazy students didn't attend labs and as a result got bad marks at the exam. So they decided that a student would be admitted to the exam only if he would attend at least one lab of each professor.
N roommates didn't know the number of labs and professors in this semester. These students had different diligence: the first student attended all labs, the second one — only labs which numbers were a multiple of two, the third one — only labs which numbers were a multiple of three, etc… At the end of the semester it turned out that only K of these students were admitted to the exam. Find the minimal N which makes that possible.

Input

An integer K (1 ≤ K ≤ 2·109).

Output

Output the minimal possible N which satisfies the problem statement. If there is no N for which exactly K students would be admitted to the exam, output 0.

Sample Input

inputoutput
8
15
3
0

Source

Ural SU Contest. Petrozavodsk Summer Session, August 2008


题解:  分析一下题目发现是一道关于欧拉函数的题,即给出phi[n]=k中的k让你求出最小的n满足phi[n]=k.  如果不存在这样的n ,就输出0。 phi函数的值 通式:φ(n)=n(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn为n的所有质因数,n是不为0的整数. 所以这道题就是将上面的过程求一次反。求出所有有的满足条件的n,然后再取最小的n。具体见下面有挫有长的代码吧:
#include<stdio.h>   #include<string.h>   #include <cmath>#include<algorithm>   #define fr(i,s,n) for(int i=s;i<n;i++)#define fi freopen("in.txt","r",stdin)#define cl(a) memset(a,0,sizeof(a))using namespace std;typedef long long ll;const int maxn=44721;ll k;bool flag[maxn+1];int prime[maxn+1];int t;void getpri(){int i,j;t=0;int n=maxn;for(i=2;i<=n;++i) {if(!flag[i]) prime[t++]=i; for(j=0;j<t&&i*prime[j]<=n;++j){ flag[i*prime[j]]=1; if(i%prime[j]==0) break; } } }ll powMod(ll a, ll b, ll m){ll r = 1ll, d = a;while (b){if (b & 1ll){r *= d;r %= m;}d *= d;d %= m;b >>= 1;}return r;}int pri[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};bool isPrime(ll x){   //判一个数是否为素if (x < 2ll) return false;if (x == 2ll) return true;if (!(x & 1ll)) return false;long long kk = 0, i, j, m, a;m = x - 1ll;while ((m & 1ll) == 0){m >>= 1;kk += 1;}for (i = 0;i < 10;i++){if (pri[i] >= x) return true;a = powMod(pri[i], m, x);if (a == 1ll) continue;for (j = 0;j < kk;j++){if (a == x - 1ll) break;a *= a;a %= x;}if (j < kk) continue;return false;}return true;}int totf=0;ll prifac[100];ll prifaccnt[100];void  getfac_prepare(ll x){   //分解质因数fr(i,0,t){if (x<prime[i]) break;if (x%prime[i]==0){prifac[totf]=prime[i];while(x%prime[i]==0){x/=prime[i];prifaccnt[totf]++;}totf++;}}if (x!=1ll) {prifaccnt[totf]=1;prifac[totf++]=x;}}ll fac[100000];int tf=0;void getfac(int pos,int x){  //求出所有的约数fac[tf++]=x;if (pos>=totf) return ;ll cur=x;fr(i,0,prifaccnt[pos]+1){getfac(pos+1,cur);cur*=prifac[pos];}}ll ans;void dfs(int pos,ll k,ll n){if (n>=ans||n*k>=ans*2ll) return;if (k==1ll){ans=n;return ;}if (pos<0) return;if (k%fac[pos]==0){ll tmpk=k/fac[pos];ll tmpn=n*(fac[pos]+1ll);while(tmpk%(fac[pos]+1ll)==0){tmpk/=(fac[pos]+1ll);tmpn*=(fac[pos]+1ll);}dfs(pos-1,tmpk,tmpn);}dfs(pos-1,k,n);}void solve(){int totprif=0;fr(i,0,tf){if (isPrime(fac[i] + 1ll)) {fac[totprif++]=fac[i];}}sort(fac,fac+totprif);totprif=unique(fac,fac+totprif)-fac;ans = 1ll << 60;dfs(totprif-1,k,1);if (ans<1ll<<60){printf("%lld\n",ans);}else printf("0\n");}int main(){getpri();while(scanf("%lld",&k)!=EOF){totf=0;getfac_prepare(k); tf=0;getfac(0,1);solve();}return 0;}


原创粉丝点击