[关闭]
@rebirth1120 2019-07-19T21:28:46.000000Z 字数 2550 阅读 832

Hankson的趣味题

解题记录 数学 算法竞赛进阶指南


题目链接:(AcWing220)Hankson的趣味题

题目大意:

组数据,每组数据给定 ,求出满足 数量。

解题思路:

质因数分解。
这道题的关键就在于由 的性质推导未知数 的质因数分解中每个质因子的指数限制。

分别为 中质因子 的次数,可得到以下限制条件。

  1. ,则
  2. ,则
  3. ,则
  4. ,则

上述限制条件可由读者自己根据 的定义和性质推导或感性理解,本人就不再赘述。其实就是我懒

上述限制分别组合,可得到 4 种情况:

1.
,则 ,否则无解;
2.
,则 ,否则无解;
3.
,则 ,否则无解;
4.
,则 ,否则无解;

那我们只需先预处理出一定范围内的质数集合,再对每个质数分别求出 ,根据限制条件,把可能的情况相乘就可以得到答案。

代码实现:

PS:这里我没有按上面的方法来求 ,导致代码量倍增……,实际上只要在所有质数表里的质数处理完后特判一下(防止 本身就是质数)就行了,但是我实在是懒得改了……,贴一个大佬的代码链接吧……Ebola 的博客 题解 P1072 【Hankson 的趣味题】(思路和我的基本一致,可以直接看代码)

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #define a0 a[0]
  7. #define a1 a[1]
  8. #define b0 a[2]
  9. #define b1 a[3]
  10. #define m1 c[0][now]
  11. #define m2 c[1][now]
  12. #define m3 c[2][now]
  13. #define m4 c[3][now]
  14. using namespace std;
  15. const int N=50000+7;
  16. const int n=50000;
  17. const int test=13;
  18. 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];
  19. bool flag;
  20. void init(){
  21. for(int i=2;i<=n;i++){
  22. if(!v[i]){
  23. v[i]=i;
  24. p[++cnt]=i;
  25. }
  26. for(int j=1;j<=cnt;j++){
  27. if(p[j]>v[i]||i*p[j]>n) break;
  28. v[i*p[j]]=p[j];
  29. }
  30. }
  31. maxn=p[cnt];
  32. backup=cnt;
  33. }
  34. void divide(int k){
  35. int tmp=a[k];
  36. for(int i=2;i<=sqrt(tmp);i++){
  37. while(tmp%i==0){
  38. tmp/=i;
  39. int t=lower_bound(p+1,p+1+cnt,i)-p;
  40. top=max(t,top);
  41. c[k][t]++;
  42. }
  43. }
  44. if(tmp!=1){
  45. if(tmp<=maxn){
  46. int t=lower_bound(p+1,p+1+cnt,tmp)-p;
  47. top=max(t,top);
  48. c[k][t]++;
  49. }
  50. else box[++box[0]]=tmp,nu[box[0]]=k;
  51. }
  52. }
  53. void extra(){
  54. for(int i=1;i<=box[0];i++)
  55. p[++cnt]=box[i];
  56. sort(p+1,p+1+cnt);
  57. for(int i=1;i<=box[0];i++){
  58. int t=lower_bound(p+1,p+1+cnt,box[i])-p;
  59. top=max(t,top);
  60. c[nu[i]][t]++;
  61. }
  62. }
  63. void clear(){
  64. cnt=backup;
  65. res=ans=1;
  66. flag=top=0;
  67. memset(c,0,sizeof(c));
  68. memset(box,0,sizeof(box));
  69. memset(nu,0,sizeof(nu));
  70. }
  71. void run(){
  72. for(int now=1;now<=top;now++){
  73. if(m1==m2&&m4==m3){
  74. if(m1>m4) { flag=1;return; }
  75. if(m4==0) continue;
  76. ans*=(m4-m1+1);
  77. }
  78. else if(m1>m2&&m4>m3){
  79. if(m2!=m4) { flag=1;return; }
  80. }
  81. else if(m1==m2&&m4>m3){
  82. if(m4<m1) { flag=1;return; }
  83. }
  84. else if(m1>m2&&m4==m3){
  85. if(m2>m4) { flag=1;return; }
  86. }
  87. }
  88. }
  89. void dfs(int now,int res){
  90. if(now==top+1) { ans++;return; }
  91. if(tag[now]==4){
  92. for(int i=be[now];i<=en[now];i++)
  93. dfs(now+1,res*pow(p[now],i));
  94. }
  95. else dfs(now+1,res*pow(p[now],be[now]));
  96. }
  97. int main(){
  98. //freopen("1.txt","r",stdin);
  99. //freopen("2.txt","w",stdout);
  100. init();
  101. cin>>T;
  102. while(T--){
  103. clear();
  104. scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
  105. for(int i=0;i<=3;i++)
  106. divide(i);
  107. if(box[0]) extra();
  108. run();
  109. if(flag) ans=0;
  110. printf("%d\n",ans);
  111. }
  112. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注