@rebirth1120
2019-07-19T13:28:46.000000Z
字数 2550
阅读 1054
解题记录 数学 算法竞赛进阶指南
有 组数据,每组数据给定 ,求出满足 的 数量。
质因数分解。
这道题的关键就在于由 的性质推导未知数 的质因数分解中每个质因子的指数限制。
设 分别为 中质因子 的次数,可得到以下限制条件。
上述限制条件可由读者自己根据 和 的定义和性质推导或感性理解,本人就不再赘述。其实就是我懒
上述限制分别组合,可得到 4 种情况:
1.
若 ,则 ,否则无解;
2.
若 ,则 ,否则无解;
3.
若 ,则 ,否则无解;
4.
若 ,则 ,否则无解;
那我们只需先预处理出一定范围内的质数集合,再对每个质数分别求出 ,根据限制条件,把可能的情况相乘就可以得到答案。
PS:这里我没有按上面的方法来求 ,导致代码量倍增……,实际上只要在所有质数表里的质数处理完后特判一下(防止 本身就是质数)就行了,但是我实在是懒得改了……,贴一个大佬的代码链接吧……Ebola 的博客 题解 P1072 【Hankson 的趣味题】(思路和我的基本一致,可以直接看代码)
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#define a0 a[0]#define a1 a[1]#define b0 a[2]#define b1 a[3]#define m1 c[0][now]#define m2 c[1][now]#define m3 c[2][now]#define m4 c[3][now]using namespace std;const int N=50000+7;const int n=50000;const int test=13;int T,a[5],c[5][N],res,ans,p[N],cnt,maxn,top,v[N],box[5],nu[5],backup,tag[N],be[N],en[N];bool flag;void init(){for(int i=2;i<=n;i++){if(!v[i]){v[i]=i;p[++cnt]=i;}for(int j=1;j<=cnt;j++){if(p[j]>v[i]||i*p[j]>n) break;v[i*p[j]]=p[j];}}maxn=p[cnt];backup=cnt;}void divide(int k){int tmp=a[k];for(int i=2;i<=sqrt(tmp);i++){while(tmp%i==0){tmp/=i;int t=lower_bound(p+1,p+1+cnt,i)-p;top=max(t,top);c[k][t]++;}}if(tmp!=1){if(tmp<=maxn){int t=lower_bound(p+1,p+1+cnt,tmp)-p;top=max(t,top);c[k][t]++;}else box[++box[0]]=tmp,nu[box[0]]=k;}}void extra(){for(int i=1;i<=box[0];i++)p[++cnt]=box[i];sort(p+1,p+1+cnt);for(int i=1;i<=box[0];i++){int t=lower_bound(p+1,p+1+cnt,box[i])-p;top=max(t,top);c[nu[i]][t]++;}}void clear(){cnt=backup;res=ans=1;flag=top=0;memset(c,0,sizeof(c));memset(box,0,sizeof(box));memset(nu,0,sizeof(nu));}void run(){for(int now=1;now<=top;now++){if(m1==m2&&m4==m3){if(m1>m4) { flag=1;return; }if(m4==0) continue;ans*=(m4-m1+1);}else if(m1>m2&&m4>m3){if(m2!=m4) { flag=1;return; }}else if(m1==m2&&m4>m3){if(m4<m1) { flag=1;return; }}else if(m1>m2&&m4==m3){if(m2>m4) { flag=1;return; }}}}void dfs(int now,int res){if(now==top+1) { ans++;return; }if(tag[now]==4){for(int i=be[now];i<=en[now];i++)dfs(now+1,res*pow(p[now],i));}else dfs(now+1,res*pow(p[now],be[now]));}int main(){//freopen("1.txt","r",stdin);//freopen("2.txt","w",stdout);init();cin>>T;while(T--){clear();scanf("%d%d%d%d",&a0,&a1,&b0,&b1);for(int i=0;i<=3;i++)divide(i);if(box[0]) extra();run();if(flag) ans=0;printf("%d\n",ans);}}