题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4497
题意:
求有多少种(x,y,z)使得最小公倍数为l,最大公约数为g
分析:
我们将l,g进行素因子分解;
非常明显当g有l没有的素因子 和g的某一个因子的次数大于l的这个因子的次数的时候答案为0;
然后是有答案的情况下,我们设g中某一个因子数的次数为num1,l中这个因子的次数为num2;
那么在决定x,y,z在这个因子上的次数时我们要这样考虑,至少有一个为num1,至少有一个为
num2,然后依据容斥原理能够得出这样的情况的方案数
代码许下:
#include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <map> using namespace std; int G[2][50],L[2][50]; int gcd(int a,int b) { if(b) return gcd(b,a%b); return a; } int main() { int t,g,l; scanf("%d",&t); while(t--){ scanf("%d%d",&g,&l); int cnt1=0,cnt2=0; memset(G,0,sizeof(G)); memset(L,0,sizeof(L)); map<int ,int >mp1; map<int ,int >mp2; for(int i=2;i<=g;i++){ if(g%i==0){ G[0][cnt1]=i; while(g%i==0){ G[1][cnt1]++; g/=i; } cnt1++; } } if(g>1){G[0][cnt1]=g;G[1][cnt1++]=1;} for(int i=2;i<=l;i++){ if(l%i==0){ L[0][cnt2]=i; while(l%i==0){ L[1][cnt2]++; l/=i; } cnt2++; } } if(l>1) {L[0][cnt2]=l;L[1][cnt2++]++;} bool flag=0; for(int i=0;i<cnt1;i++) mp1[G[0][i]]=G[1][i]; for(int i=0;i<cnt2;i++) mp2[L[0][i]]=L[1][i]; for(int i=0;i<cnt1;i++){ if(mp1[G[0][i]]>mp2[G[0][i]]) flag=1; } if(flag){ puts("0"); continue;} long long ans=1; //cout<<cnt1<<" "<<cnt2<<endl; /***** cout<<"*******"<<endl; for(int i=0;i<cnt1;i++) cout<<G[0][i]<<" "<<G[1][i]<<endl; cout<<"*******"<<endl; for(int i=0;i<cnt2;i++) cout<<L[0][i]<<" "<<L[1][i]<<endl; cout<<"*******"<<endl; ******/ for(int i=0;i<cnt2;i++){ int num1=mp1[L[0][i]]; int num2=mp2[L[0][i]]; if(num1==num2) continue; long long tmp = (num2-num1+1)*(num2-num1+1)*(num2-num1+1); tmp-=2*(num2-num1)*(num2-num1)*(num2-num1); tmp+=(num2-num1-1)*(num2-num1-1)*(num2-num1-1); ans*=tmp; cout<<"tmp "<<tmp<<endl; } cout<<ans<<endl; } return 0; }