BZOJ3643-欧拉函数,搜索
2017-10-25 01:50
411 查看
给定一个数x,我们可以求出phi(x)
那给定一个数k(k<1e6),如何求出phi(x)=k的解呢
容易知道k为奇数时唯有k=1有解x=1,其余无解
假设n有素幂因子分解$n={p_1}^{a_1}{p_2}^{a_2}\cdots{p_k}^{a_k}$
因为$\phi(x)=\prod\limits_{j=1}^{k}{p_j}^{a_j-1}(p_j-1)$
所以$1<p_j<=k$且$(p_j-1)\mid k$
由此筛选出一些质数,同时记录它的最高幂次
然后用dfs遍历所有的情况,找到答案就将答案加入ans
以k=8为例,设$x=2^a3^b5^c$
对于2,有$(2-1)2^{a-1}\mid 8$,则a最大为4
对于3,有$(3-1)3^{b-1}\mid 8$,则b最大为1
对于5,有$(5-1)5^{c-1}\mid 8$,则c最大为1
再进行bfs搜索,得到可行解
发现某些偶数是无解的,随着x的增大,phi(x)似乎越来越稀疏
那给定一个数k(k<1e6),如何求出phi(x)=k的解呢
容易知道k为奇数时唯有k=1有解x=1,其余无解
假设n有素幂因子分解$n={p_1}^{a_1}{p_2}^{a_2}\cdots{p_k}^{a_k}$
因为$\phi(x)=\prod\limits_{j=1}^{k}{p_j}^{a_j-1}(p_j-1)$
所以$1<p_j<=k$且$(p_j-1)\mid k$
由此筛选出一些质数,同时记录它的最高幂次
然后用dfs遍历所有的情况,找到答案就将答案加入ans
以k=8为例,设$x=2^a3^b5^c$
对于2,有$(2-1)2^{a-1}\mid 8$,则a最大为4
对于3,有$(3-1)3^{b-1}\mid 8$,则b最大为1
对于5,有$(5-1)5^{c-1}\mid 8$,则c最大为1
再进行bfs搜索,得到可行解
a | b | c | x |
0 | 1 | 1 | 15 |
4 | 0 | 0 | 16 |
2 | 0 | 1 | 20 |
3 | 1 | 0 | 24 |
1 | 1 | 1 | 30 |
代码
#include <vector> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int N=500000+5; bool prime ; int p , tot=0; //线筛 void initP(){ for(int i=2;i<N;i++)prime[i]=true; for(int i=2;i<N;i++){ if(prime[i])p[tot++]=i; for(int j=0;j<tot&&i*p[j]<N;j++){ prime[i*p[j]]=false; if(i%p[j]==0)break; } } } //快速幂 LL qpow(LL a,LL b){ LL ret=1; while(b){ if(b&1)ret=(ret*a); a=(a*a); b>>=1; } return ret; } typedef pair<LL,LL> pr; vector<LL> ans; vector<pr>v; int num[100];//保存状态 void add(){ LL ret=1; for(int i=0;i<v.size();i++){ if(num[i])ret*=qpow(v[i].first,num[i]); } ans.push_back(ret); } //now代表当前状态的欧拉函数值 void dfs(int cur,LL now,LL n){ if(now==n&&cur==v.size())add();//找到答案 if(now>n||cur==v.size())return;//剪枝与边界 dfs(cur+1,now,n); //cur位置上的数为0 now*=v[cur].first-1; num[cur]=1; dfs(cur+1,now,n); //cur位置上的数为1 for(int i=1;i<v[cur].second;i++){ now*=v[cur].first; num[cur]++; dfs(cur+1,now,n); //cur位置上的数>1 } num[cur]=0; //回溯 } bool isPrime(LL n){ if(n<N)return prime ; for(int i=0;i<tot;i++){ if(n%p[i]==0)return false; } return true; } void solve(LL n){ v.clear(); ans.clear(); memset(num,0,sizeof num); LL m,tmp,last=n; //分解质因数 for(int i=0;i<tot&&p[i]<n;i++){ if(n%(p[i]-1)==0){ m=1; tmp=n/(p[i]-1); while(tmp%p[i]==0)m++,tmp/=p[i]; //printf("%d - %d\n",p[i],m); v.push_back(pr(p[i],m)); } } if(isPrime(n+1))v.push_back(pr(n+1,1)); dfs(0,1,n); sort(ans.begin(),ans.end()); //排序 } int main(){ initP(); LL n; while(~scanf("%lld",&n)){ solve(n); if(ans.size()==0||ans[0]>(1LL<<31))printf("-1\n"); else printf("%lld\n",ans[0]); } return 0; }
相关文章推荐
- [BZOJ3643]Phi的反函数(数学相关+搜索)
- 【BZOJ 3643】Phi的反函数 数搜索
- BZOJ 4803(逆欧拉函数-搜索)
- 【NOIP 模拟题】【bzoj 3643】Phi的反函数(数论+搜索)
- BZOJ 3643|Phi的反函数|搜索|线性筛法
- [BZOJ3643] phi的反函数 - 欧拉函数 - dfs
- 【BZOJ-3643】Phi的反函数 数论 + 搜索
- BZOJ3643 Phi的反函数(数论+搜索)
- BZOJ 3643: Phi的反函数 搜索
- BZOJ 4803: 逆欧拉函数 素数测试 搜索
- bzoj 3643:Phi的反函数 (数论+搜索)
- [BZOJ2818] gcd - 欧拉函数+筛法
- BZOJ - 2705: [SDOI2012]Longge的问题 【欧拉函数 一道必做的经典题】
- 【bzoj2186】沙拉公主的困惑 欧拉函数+乘法逆元
- bzoj 4805: 欧拉函数求和 杜教筛
- BZOJ 1024 生日快乐 搜索 DFS
- bzoj 2818 Gcd(欧拉函数 | 莫比乌斯反演)
- 【BZOJ1016】[JSOI2008]最小生成树计数【最小生成树】【搜索】
- BZOJ 3884: 上帝与集合的正确用法(欧拉函数)——有趣的题目
- [BZOJ 2705][SDOI 2012]Longge的问题(欧拉函数)