题目描述
现在给了a0,a1,b0,b1四个数,问有多少个x满足 gcd(a0,x)=a1,lcm(x,b0)=b1;
样例
输入:
1 2 3
| 2 41 1 96 288 95 1 37 1776
|
输出:6 2
算法
由于b1是lcm(x,b0) 那必然x就是b1的约数,所以只要枚举出所有的b1的约束,满足条件的就是x
那如何求b1的约数呢,如果是单纯的暴力那肯定是超时的。
但是我们可以记录所有b1的质因子并且每个质因子的个数,来达到因式分解的目的;
(线性筛的板子写假了 primes写成了bool类型 每个质数都是1抽了一晚的烟都没看出来哪里超时了)
for(int i=1;primes[i]*primes[i]<=h&&i<=cnt;i++)
{
int s=0;
while(h%primes[i]==0) s++,h/=primes[i];
if(s!=0)in[++cntd]={primes[i],s};
}
然后再根据质因子以及每个质因子的个数深搜枚举即可
dfs(1,1);//深搜入口,第1个质因子,当前的值为1
深搜的过程
1 2 3 4 5 6 7
| void dfs(int u,int k){ if(u>cntd) {ans[++cntf]=k;return ;}//如果记录的所有质因子都遍历完那就结束 for(int i=0;i<=in[u].second;i++){ dfs(u+1,k); k*=in[u].first;//枚举每个因子的数量 } }
|
C++ 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| #include <bits/stdc++.h>
using namespace std;
#define PII pair<int,int> int cnt=0; bool st[100010]; int primes[100010]; PII in[100010]; int num[100010]; void init(int k){ for(int i=2;i<=k;i++){ if(!st[i])primes[++cnt]=i; for(int j=1;i*primes[j]<=k&&j<=cnt;j++){ st[i*primes[j]]=1; if(i%primes[j]==0) break; } } } int ans[1000100]; int cntd=0,cntf=0;
void dfs(int u,int k){ if(u>cntd) {ans[++cntf]=k;return ;} for(int i=0;i<=in[u].second;i++){ dfs(u+1,k); k*=in[u].first; } }
void solve(){ int a0,a1,b0,b1; cin>>a0>>a1>>b0>>b1; cntd=0,cntf=0; int h=b1; for(int i=1;primes[i]*primes[i]<=b1&&i<=cnt;i++) { int s=0; while(h%primes[i]==0) s++,h/=primes[i]; if(s!=0)in[++cntd]={primes[i],s}; } if(h>1)in[++cntd]={h,1}; dfs(1,1); int res=0; //cout<<cntf<<"+++"; for(int i=1;i<=cntf;i++){ if(__gcd(ans[i],a0)==a1&&(long long)ans[i]*b0/__gcd(ans[i],b0)==b1) res++; } cout<<res<<endl; }
signed main(){ init(100000); int _; cin>>_; while(_--){ solve(); } }
|
所以呢就不快乐。