/**//* 给出n,问满足phi(k) = n的k的个数,其中k的素因子个数<=3 n<2^31 欧拉函数 phi(k) = k(1-1/p1)(1-1/p2)(1-1/p3) = (p1-1)p1^x*(p2-1)p2^y*(p3-1)p3^z phi(1) = 1
比赛时打算筛素数(筛到sqrt(2^31)),枚举p1,p2,p3 有问题的,比如 n = (3-1) * p 当n很大时,这样p就是一个很大的数了,而素数表没有,就枚举不到了!
问了ACOrz,他的代码很神奇呀 因为n = (p1-1)p1^x*(p2-1)p2^y*(p3-1)p3^z 用sqrt(n)枚举(pi-1) if(n%(pi-1) && isPrime(pi))加入pi 然后就dfs出最多3个数,让 (p1-1)p1^x*(p2-1)p2^y*(p3-1)p3^z = n 注意的是phi(1) = 1 所以n=1时,满足条件的有2个,即k=1,2 ACOrz的代码很简洁,下面是我按照我的风格模仿他写的 注意枚举的是(pi - 1),不是n的素因子 !!! */ #include<iostream> #include<cstring> #include<map> #include<algorithm> #include<stack> #include<queue> #include<cmath> #include<string> #include<cstdlib> #include<vector> #include<cstdio> #include<set> #include<list> #include<numeric> #include<cassert> #include<ctime>
using namespace std;
vector<int> prime; int ans;
bool isPrime(int n){ for(int p = 2; p <= n/p ; p++){ if(n % p == 0){ return false; } } return true; }
void dfs(int next, vector<int> with, int n){ int nn = n; bool can = true; for(vector<int>::iterator it = with.begin() ; it != with.end() ; it++){//检查合法性 if(n % (*it-1) == 0) { n /= (*it-1); }else { can = false; break; } } if(can){ //with可以为空!!! for(vector<int>::iterator it = with.begin() ; it != with.end() ; it++){ while(n % *it == 0){ n /= *it; } } if(n == 1)ans++;//特殊情况是with为空,但原始的n为1 if(with.size() == 3){ return; } for(int i = next ; i < prime.size(); i++){//扩展 with.push_back(prime[i]); dfs(i+1, with, nn); with.pop_back(); } } }
int main() { #ifndef ONLINE_JUDGE //freopen("in","r",stdin); #endif
for(int n; ~scanf("%d", &n); ){ prime.clear(); for(int i = 1 ; i <= n / i; i++){ if(n % i == 0){ if(isPrime(i+1)){ prime.push_back(i+1); } if(n/i != i && isPrime(n/i+1)){ prime.push_back(n/i+1); } } } ans = 0; dfs(0, vector<int>(), n); printf("%d\n", ans); } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|