Problem Description
In mathematics, the greatest common divisor (gcd), of two non-zero integers, is the largest positive integer that divides both two numbers without a remainder. For example, gcd( 10, 15 ) = 5, gcd( 5, 4 ) = 1. If gcd( k, n ) == 1 , then we say k is co-prime to n ( also , n is co-prime to k ), the totient function H(n) of a positive integer n is defined to be the number of positive integers not greater than n that are co-prime to n. In particular H(1) = 1 since 1 is co-prime to itself (1 being the only natural number with this property). For example, H (9) = 6 since the six numbers 1, 2, 4, 5, 7 and 8 are co-prime to 9. Also, we define the number of different prime of n is P (n). For example, P (4) = 1 (4 = 2*2), P (10) = 2(10 = 2*5), P (60) = 3(2*2*3*5). Now, your task is, give you a positive integer n not greater than 2^31-1, please calculate the number of k (0 < k < 2^31) satisfied that H (k) = n and P (k) <= 3(So we called HP Problem).
Input
Each line will contain only one integer n. Process to end of file.
Output
For each case, output the answer in one line.
Sample Input
6
Sample Output
4
思路:给定n为在[1,2^31-1]范围内有多少个数满足 H(k)=n&& P(k)<=3;
H(k)为k的欧拉函数;P(K)为k中所含质因子的种类个数;
欧拉公式:如果k=p1^q1 *P2^q2*....*pm^qm;
则H(k)=k*(p1-1)*(p2-1)...(pm-1)/(p1*p2*p3*p4...pm)
如果已知H(k)以及k中质因子(p1, p2, p3, p4,..pm)则可以唯一确定一个k=H(k)*(p1*p2*...*pm)/((p1-1)*(p2-1)...*(pm-1))
于是对于n,如果找到了质因子集合{p1,p2,...,pm}( m<=3)则等于找到了一个k;
同时这样的质因子集合满足
n%(pi-1)==0&&n 不含集合外的其他质因子;同时求得的K应小于2^31;
由于m<=3可以枚举具有上述性质的质因子集合来得到答案;
n为1时,有2个,H(1)=1这种特殊情况要考虑。
(真心看不懂啊……)

#include<stdio.h> #include<queue> #include<string.h> #include<math.h> #include<stdlib.h> #include<memory> #include<map> #include<set> #include<vector> #include<algorithm> #include<malloc.h> #include<iostream> using namespace std; typedef __int64 ll; #define N 100000 #define M_F 1000 const ll base=2147483648; int tag[N]; ll prime[N/10],cnt; ll p[M_F],q[M_F],num; ll a[M_F],m; ll ans,n,pr[10],t; void get_prime() { int i,j; memset(tag,0,sizeof(tag)); for(i=2;i*i<N;i++) if(!tag[i]) { for(j=2;j*i<N;j++) tag[j*i]=1; } for(i=2,cnt=0;i<N;i++) if(tag[i]==0)prime[cnt++]=i; } void factor() { int i; ll tmp=n; for(num=0,i=0;i<cnt&&prime[i]*prime[i]<=n;i++) if(n%prime[i]==0) { p[num]=prime[i]; q[num]=0; while(n%prime[i]==0) { q[num]++; n/=prime[i]; } num++; } if(n>1) { p[num]=n; q[num++]=1; } n=tmp; } int Is_Ok(ll cur) { int i; cur++; for(i=0;i<cnt&&prime[i]*prime[i]<=cur;i++) if(cur%prime[i]==0)return 0; return 1; } void dfs(ll cur,int idx) { ll tmp=1; if(idx>=num) { if(Is_Ok(cur))a[m++]=cur; return ; } for(int i=0;i<=q[idx];i++) { dfs(cur*tmp,idx+1); tmp=tmp*p[idx]; } } int judge() { ll ret,tmp; ret=n; int i; for(i=0;i<t;i++) { if(ret%(pr[i]-1))return 0; else ret/=(pr[i]-1); } for(i=0;i<t;i++) { ret=ret*pr[i]; if(ret>=base||ret<0)return 0; } //tmp=ret; ret=n; for(i=0;i<t;i++) { ret/=(pr[i]-1); } for(i=0;i<t;i++) while(ret%pr[i]==0)ret/=pr[i]; //if(ret==1)cout<<tmp<<endl; return (ret==1); } void dfs1(int idx,int k) { if(k>3)return ; else { if(k) { t=k; ans+=judge(); } int i; for(i=idx;i<m;i++) { pr[k]=a[i]+1; dfs1(i+1,k+1); } } } int main() { get_prime(); while(scanf("%I64d",&n)!=EOF) { factor(); m=0; dfs(1,0); ans=0; dfs1(0,0); if(n==1)ans++; printf("%I64d\n",ans); } return 0; }