题目背景
水几绕,山几重,何处金陵城。
访名都,寻形胜,龙虎倚江东。
书留翰墨,曲落潮声。
草木几度枯荣。
——银临《金陵谣》
题目描述
江苏南京,亦称金陵,是一座历史文化名城。有了古城的衬托,江苏省的高考模拟题都显地那么棘手,难以解决。切切在一轮复习过程中便碰到一道江苏省模拟题,在七瑾的帮助下,切切很快秒杀了该题,但切切觉得不够,想用这道题来刁难你。解决本题就能吃到切切和七瑾撒的糖。
给定四个正整数 a,b,c,da, b, c, da,b,c,d,求有多少对正整数 (x,y)(x, y)(x,y) 满足
ax+bc=dyfrac a x + frac b c = frac d y xa+cb=yd
输入格式
本题单测试点内有多组测试数据。
第一行是一个整数,表示数据组数 TTT。
接下来 TTT 行,每行四个整数,依次表示一组数据的 a,b,c,da, b, c, da,b,c,d。
输出格式
对于每组数据,输出一行一个整数表示答案。
输入输出样例
1 1 1 3 2
3
说明/提示
样例 1 解释
求 1x+13=2yfrac 1 x + frac 1 3 = frac 2 yx1+31=y2 的正整数解对数,分别是 (x=3,y=3)(x = 3, y = 3)(x=3,y=3),(x=6,y=4)(x = 6, y = 4)(x=6,y=4),(x=15,y=5)(x = 15, y = 5)(x=15,y=5)。
数据规模与约定
本题共有 20 个测试点,每个测试点 555 分。
- 对于测试点 111,保证 T=0T = 0T=0。
- 对于测试点 2∼162 sim 162∼16,共 151515 个测试点,对于 a,b,c,da, b, c, da,b,c,d 四个数中至少存在一个数为 111 共有 151515 种情况,每个测试点对应一种情况。
- 对于测试点 17∼2017 sim 2017∼20,没有特殊约定。
对于全部的测试点,保证 0≤T≤200 leq T leq 200≤T≤20,1≤a,b,c,d≤1061 leq a, b, c, d leq 10^61≤a,b,c,d≤106,d×c≤106d imes c leq 10^6d×c≤106。
提示
- 众所周知,高考不考数论。
- 本题共有两个样例文件,见附加中的 song.zip。
附件下载
song.zip 633B
我们发现题面依旧有点bug....不过没关系,我们看的是内容,题目它不重要(我在说peach)
好了,开始正题,来说一说我的扫黄记录....
先说一下正解,再来谈一下经历,老套路了~~
首先我们观察题目,发现良心的出题人扶苏给我们了亿点点的提示:d*c<=10^6
看见了吗?这说明这道题目和d*c绝对有着密切关系,再看问题,哎呦,不就是让你求一个解的个数吗?不慌不慌,看看样例稳住心情(没错,这就是小蒟蒻我的真实心路历程,原来一个简简单单的求解的个数问题就可以使我如此卑微...)妙啊,我们再一次感谢良心的出题人扶苏,看到没有数据说明提示里面y是按照3 4 5 的顺序排列的,这又说明了什么?说明了这个题肯定不是采取一些什么神奇的知识才能解决出来的神奇题目,它是一个暴力枚举循环!!!cheer up!!
想到这一层我们就可以放心大胆的退式子了,主要思想其实就是把y用x表示出来或者把x用y表示出来,(这里其实用y表示x会更好,这样的话式子就会变成x=a*c*y/(d*c-b*y),题目中给出的爱意满满的提示d*c<=10^6就可以用上了,但是如果你一开始没有按照这种方式推式子,那么其实也没有关系,通过约分化简的手段同样可以产生关于d*c的式子),通过对y或x的枚举,判断式子右边是否为整数,就可以完美AC
经验干货(血泪教训):
1.数论题,不管是什么,只要你觉得这个题看起来这么像数学题的,一定开long long!!!开long long!!!!开long long!!!!!~(40——>100)
2.负数不可以直接进行取模运算,如果你这么干了,你的程序会随时崩掉....
3.注意题目特殊条件:比如这个题里面,abcd是整数,而不是正整数,所以要小心abcd可能为负数的情况(当然毕竟我不是出题人,我也不知道测试数据里面到底给没给负数的点)
#include<bits/stdc++.h> using namespace std; long long t,a,b,c,d; int main() { cin>>t; if(t==0) { return 0; } while(t--) { cin>>a>>b>>c>>d; long long sum=(d*c)/b; // cout<<sum<<endl; if(sum<0) return 0; long long ans=0; for(int i=1;i<=sum;i++) { // cout<<"*****"<<endl; if(a*c*i<0) break; else if((d*c-b*i>0)&&(a*c*i)%(d*c-b*i)==0) ans++; } cout<<ans<<endl; } return 0; }