• 【NOIP2009】Hankson 的趣味题


    题目描述

    Hanks 博士是 BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson。现在,刚刚放学回家的 Hankson 正在思考一个有趣的问题。
    今天在课堂上,老师讲解了如何求两个正整数 c1 和 c2 的最大公约数和最小公倍数。现在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数 a0,a1,b0,b1,设某未知正整数 x 满足:
    1. x 和 a0 的最大公约数是 a1;
    2. x 和 b0 的最小公倍数是 b1。
    Hankson 的“逆问题”就是求出满足条件的正整数 x。但稍加思索之后,他发现这样的x 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 x 的个数。请你帮助他编程求解这个问题。

    解题报告:

    写着好玩,好像和网上题解有些不一样
    这题可以从c和d下手,考虑c和d的质因子,如果d的某个质因子和c的某个质因子的出现次数相同,那么x就可以取任意个(不超过d)该质因子。
    如果c的质因子和d的质因子出现的不相同,那么x含有该因子的次数就确定了,可以直接乘起来。
    最后我们把不确定的质因子dfs枚举出现次数,然后暴力判断 (gcd(x,a0)==a1) 即可

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    const int N=45005;
    int a,b,c,d,pri[N],num=0,n=0;bool vis[N];
    int li=1;
    void getpri(){
       for(int i=2;i<N;i++){
          if(!vis[i])pri[++num]=i;
          for(int j=1;j<=num && pri[j]*i<N;j++){
             vis[pri[j]*i]=true;if(i%pri[j]==0)break;
          }
       }
    }
    struct node{
       int x,t;
    }q[N];
    int qm(int x,int k){
       int sum=1;
       while(k){if(k&1)sum*=x;x*=x;k>>=1;}
       return sum;
    }
    bool check(int y,int goal){
       int x=c,cnt=0;
       while(x%y==0)x/=y,cnt++;
       return cnt!=goal;
    }
    int ans=0;
    int gcd(int x,int y){return x%y?gcd(y,x%y):y;}
    void dfs(int dep,int cnt,int tot){
       if(dep==n+1){
          if(gcd(tot,a)==b)ans++;
          return ;
       }
       if(cnt<q[dep].t)dfs(dep,cnt+1,tot*q[dep].x);
       dfs(dep+1,0,tot);
    }
    void work()
    {
       int cnt=0,x;n=0;ans=0;li=1;
       scanf("%d%d%d%d",&a,&b,&c,&d);x=d;
       for(int j=1;j<=num && pri[j]<=x;j++){
          cnt=0;
          while(x%pri[j]==0)x/=pri[j],cnt++;
          if(check(pri[j],cnt))li*=qm(pri[j],cnt);
          else q[++n].x=pri[j],q[n].t=cnt;
       }
       if(x>1){
          if(check(x,1))li*=x;
          else q[++n].x=x,q[n].t=1;
       }
       dfs(1,0,li);
       printf("%d
    ",ans);
    }
    
    int main()
    {
    	int T;cin>>T;getpri();
        while(T--)work();
    	return 0;
    }
    
    
  • 相关阅读:
    @RequestParam方式传入list
    编写优美代码的七条规范(Python版)
    汇编程序设计入门
    CSP-S2020解题报告(待完成!)
    [USACO18JAN]MooTube
    DP优化
    AFO记
    考前总结
    清北学堂周末刷题班第五场
    清北学堂考前综合刷题班第四场
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7622878.html
Copyright © 2020-2023  润新知