https://www.luogu.org/problemnew/show/P1072(题目传送)

数学的推理在编程的体现越来越明显了。(本人嘀咕)

首先,我们知道这两个等式: (a0,x)=a1,[b0,x]=b1(a0,x)=a1,[b0,x]=b1

于是,我们可以设: x=a1*p,b1=x*tx=a1∗p,b1=x∗t

于是有: a1*p*t=b1a1∗p∗t=b1

所以我们令: b1/a1=sb1/a1=s

则: p*t=sp∗t=s

即: t=s/pt=s/p

又由最大公约数与最小公倍数的定义与性质可得:

(a0/a1,p)=1,(b1/b0,t)=1(a0/a1,p)=1,(b1/b0,t)=1

所以我们令: a0/a1=m,b1/b0=na0/a1=m,b1/b0=n

则有: (p,m)=1,(s/p,n)=1(p,m)=1,(s/p,n)=1

这就是第一个结论,我们称其为结论一。事实上,我们其实已经可以由结论一整理出可以AC的方法,即用sqrt(s)的复杂度枚举s的因数,然后将每个因数放到结论一中,看看是否成立,再统计所有符合结论一的因数的个数,然后输出即可。这种算法的复杂度是:O(sqrt(s)*log(s)*n)。这样其实也能卡过数据,但是还是没有达到理论上的通过。所以我们还要继续优化。

我们考虑(s/p,n)=1。如果s/p与n有相同质因数,则无法使(s/p,n)=1成立。于是,为了使(s/p,n)=1成立,我们可以将s与n所有相同的质因数从s中去掉(不动s/p的原因是s/p是s的因变量,改变无意义),得到剩余的数l,若(s/p,n)=1成立,s/p就必须是l的约数。

我们继续考虑(p,m)=1。因为s/p是l的约数,那么p就一定可以表示为这样的形式:

p=(s/l)*r(因为s/p*r=p,r属于N*

即:p一定是s/l的倍数(因为s/p是l的约数),r也是l的约数。于是就又有:

r|l,且(r,m)=1

这就是第二个结论,我们称其为结论二。而解决结论二的方法便很明显了。我们可以用与解决结论一相似的方法,将l与m所有相同的质因数从l中去掉,得到剩余的数q。那么所有使结论二成立的r都是q的因数了。然后,我们可以用sqrt(q)的复杂度枚举q的所有因数,输出q的因数个数就行了。这样,复杂度便降到了:O((sqrt(s)+log(s))*n),从理论来说也不会超时了。

还有一点需要注意,那就是特判没有符合要求的x的情况。这种情况出现只有四种可能:

1、s不为整数

2、m不为整数

3、n不为整数

4、(s/l,m)≠1,即因为p是s/l的倍数,所以无论r取何值,都会有(p,m)≠1

加上这四个特判,这道题便做完了。(来个总结公式:结论成立=筛去必要条件的不足+必要条件,这也算是一种思路吧)

AC代码:

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int ssqrt;
int cf(int a,int b)//去掉a中与b共有的质因数。思想:将b质因数分解,同时将a中与b共有的质因数去掉。
{
ssqrt=sqrt(b);
for(int i=;i<=ssqrt;i++)//sqrt(b)复杂度质因数分解b
{
if(b%i==)while(a%i==)a/=i;//去掉a中与b共有的质因数,将a分解
while(b%i==)b/=i;//将b质因数分解
}
if(b!=)while(a%b==)a/=b;//注意:此时b可能还不是1,因为b可能有比sqrt(b)更大的质因数,但至多只有一个,且它的次幂至多是1。所以如果b不是1,那就只能是一个质数。于是此时继续分解a。
return a;//返回剩下的a
}
int gcd(int a,int b){return b==?a:gcd(b,a%b);}//辗转相除求最大公约数
int main()
{
int a0,a1,b0,b1;
int gs;
int m,n,s,l,q;
scanf("%d",&gs);
int cnt;
while(gs--)
{
scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
if(a0%a1|b1%b0|b1%a1){printf("0\n");continue;}//如果m、n、s中有小数,则直接输出0。这里的代码用到了一些位运算
m=a0/a1,n=b1/b0,s=b1/a1;l=cf(s,n);//求出m、n、s,然后求出l
if(gcd(max(s/l,m),min(s/l,m))!=){printf("0\n");continue;}//如果不互质,则直接输出0
q=cf(l,m);cnt=,ssqrt=sqrt(q);//求出q,开始枚举q的因数,求出q的因数个数
for(int i=;i<=ssqrt;i++)if(q%i==)cnt+=i==q/i?:;//这里注意,如果i==q/i,则只加1,否则加2
printf("%d\n",cnt);//输出
}
return ;

另附应用结论一的代码(好像更快。。。估计上面代码cf函数拖时间了吧):

 #include<cstdio>
using namespace std;
int gcd(int a,int b) {
return b==?a:gcd(b,a%b);
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
int a0,a1,b0,b1;
scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
int p=a0/a1,q=b1/b0,ans=;
for(int x=1;x*x<=b1;x++) //精华
if(b1%x==){
if(x%a1==&&gcd(x/a1,p)==&&gcd(q,b1/x)==) ans++;
int y=b1/x;//得到另一个因子
if(x==y) continue;
if(y%a1==&&gcd(y/a1,p)==&&gcd(q,b1/y)==) ans++;
}
printf("%d\n",ans);
}
return ;
}

做题在纸上推理推理写写思路,更清晰地解题


给看到这里的OIer一个小干货吧(虽然很可能知道,但也是试了好久才总结出来的啊):cmd的窗口默认保存297行,宽80字符,高25字符

洛谷P1072 Hankson 的趣味题(题解)的更多相关文章

  1. 洛谷 P1072 Hankson 的趣味题 题解

    题面 提前知识:gcd(a/d,b/d)*d=gcd(a,b); lcm(a,b)=a*b/gcd(a,b); 那么可以比较轻松的算出:gcd(x/a1,a0/a1)==gcd(b1/b0,b1/x) ...

  2. 洛谷 P1072 Hankson 的趣味题 解题报告

    P1072 \(Hankson\)的趣味题 题目大意:已知有\(n\)组\(a0,a1,b0,b1\),求满足\((x,a0)=a1\),\([x,b0]=b1\)的\(x\)的个数. 数据范围:\( ...

  3. 洛谷P1072 Hankson 的趣味题

    P1072 Hankson 的趣味题 题目描述 Hanks 博士是 BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson.现在,刚刚放学回家的 Hankson 正在思考一 ...

  4. Java实现洛谷 P1072 Hankson 的趣味题

    P1072 Hankson 的趣味题 输入输出样例 输入 2 41 1 96 288 95 1 37 1776 输出 6 2 PS: 通过辗转相除法的推导 import java.util.*; cl ...

  5. 【题解】洛谷P1072 Hankson的趣味题 (gcd和lcm的应用)

    洛谷P1072:https://www.luogu.org/problemnew/show/P1072 思路 gcd(x,a0)=a1 lcm(x,b0)=b1→b0*x=b1*gcd(x,b0) ( ...

  6. 洛谷 P1072 Hankson 的趣味题

    题目描述 Hanks 博士是 BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson.现 在,刚刚放学回家的 Hankson 正在思考一个有趣的问题. 今天在课堂上,老师讲 ...

  7. [NOIP2009] 提高组 洛谷P1072 Hankson 的趣味题

    题目描述 Hanks 博士是 BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson.现 在,刚刚放学回家的 Hankson 正在思考一个有趣的问题. 今天在课堂上,老师讲 ...

  8. 洛谷P1072 Hankson的趣味题

    这是个NOIP原题... 题意: 给定 a b c d 求 gcd(a, x) = b && lcm(c, x) = d 的x的个数. 可以发现一个朴素算法是从b到d枚举,期望得分50 ...

  9. 洛谷 - P1072 Hankson - 的趣味题 - 质因数分解

    https://www.luogu.org/problemnew/show/P1072 一开始看了一看居然还想放弃了的. 把 \(x,a_0,a_1,b_0,b_1\) 质因数分解. 例如 \(x=p ...

随机推荐

  1. 算法: 整数中1出现的次数(从1到n整数中1出现的次数)

    问题: 整数中1出现的次数(从1到n整数中1出现的次数) 问题:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数? 为此他特别数了一下1~13中包含1的数字有1.10.11 ...

  2. PJSUA2开发文档--第九章 PJSUA2应用程序示例

    9. PJSUA2示例应用程序 9.1 示例应用程序 9.1.1 C++ pjsip-apps/src/samples/pjsua2_demo.cpp 是一个非常简单可用的C++示例应用程序. /* ...

  3. ASP.NET Zero--前期要求

    前期要求 需要以下工具才能使用ASP.NET Zero Core解决方案: Visual Studio 2017 + Visual Studio扩展: Bundler&Minifier Web ...

  4. 搭建一个dubbo+zookeeper平台

    本篇主要是来分享从头开始搭建一个dubbo+zookeeper平台的过程,其中会简要介绍下dubbo服务的作用. 首先,看下一般网站架构随着业务的发展,逻辑越来越复杂,数据量越来越大,交互越来越多之后 ...

  5. June. 24th 2018, Week 26th. Sunday

    Beautiful things don't ask for attention. 真正美丽的东西,并不会刻意寻求别人的注目. From The Secret Life of Walter Mitty ...

  6. const int *p;int *const p;区别及用法

    在单片机程序设计中,我们经常会用到const这个关键字,在有些单片机的编译器中可能会是code(比如51系列单片机),但我们在学习C语言的时候,首先还是先学到的const.我们知道,const关键字的 ...

  7. ipa企业签名

    包天包周包月季度包年套餐_app/ios应用企业签名_ios企业签名 常见问题 需要提供 App 的源码吗? 不需要源码,只发 ipa 或者 app 格式的安装包即可. 客户怎么安装签名好的软件? 安 ...

  8. Python两大佬互相撕逼 技术何苦为难技术?

    最近两天 Python 圈发生了一件大事,两个 Python 大佬撕逼了起来了. 不,其实是一个大佬(刘志军)被怼. 事情是这样的. 背景 人物介绍: 董明伟:公众号「Python 之美」的作者,似乎 ...

  9. CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash

    传送门--Luogu 传送门--Codeforces 如果存在长度\(>3\)的等差子序列,那么一定存在长度\(=3\)的等差子序列,所以我们只需要找长度为\(3\)的等差子序列.可以枚举等差子 ...

  10. Foundation框架 - 结构体

    一.基础知识 如果要想使用 Foundation 框架的数据类型,那么包含它的主头文件就可以了.即 #import <Foundation/Foundation.h> 补充: Core F ...