codevs 1213 解的个数
2017-04-06 17:10
246 查看
1213 解的个数
时间限制: 1 s空间限制: 128000 KB
题目等级 : 黄金 Gold
题目描述 Description
已知整数x,y满足如下面的条件:
ax+by+c = 0
p<=x<=q
r<=y<=s
求满足这些条件的x,y的个数。
输入描述 Input Description
第一行有一个整数n(n<=10),表示有n个任务。n<=10
以下有n行,每行有7个整数,分别为:a,b,c,p,q,r,s。均不超过108。
输出描述 Output Description
共n行,第i行是第i个任务的解的个数。
样例输入 Sample Input
2
2 3 -7 0 10 0 10
1 1 1 -10 10 -9 9
样例输出 Sample Output
1
19
数据范围及提示 Data Size & Hint
分类标签 Tags 点此展开
神坑啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊以下内容摘自某大神的题解
1.首先我们可以很直观地看出来这是用扩展欧几里得算法解二元一次方程,但问题是我们所熟悉的扩欧能解的方程都是ax+by=gcd(a,b)形式的,而题目给出的是ax+by=-c形式。举个例子:
2x+4y=18,首先我们可以换成x+2y=9形式。9不是2和4的最大公约数1,但9是1的倍数,所以如果我们解出一组x,y满足x+2y=1,那么x和y都乘上9/1就是原方程的一组解了。如果c/gcd(a,b)==0,那么就没有整数解。
2.如今我们得到了一组x,y,根据扩欧定理的后续内容,适合的解系一定是(x+bk,y-ak),注意现在的a,b是简化后的方程的系数(拿上面提到的例子讲,现在a=1,b=2),枚举找在区间内的解的个数(组数)就好。
3.现在解决各种WA/TLE/RE问题:
(1)方程无解:c/gcd(a,b)==0,直接输出0;
(2)区间不合法:题目中没有保证区间左端点小于右端点,所以如果读入的区间不合法,直接输出0;
(3)a=0或b=0:
if((a==0)&&(y<r||y>s)) {printf("0\n");continue;}
if((b==0)&&(x<p||x>q)) {printf("0\n");continue;}
因为不管加多少,x/y还是原来的味道……但是如果不加特判可能会导致TLE(这个跟代码具体的写法有关,我后面有用while循环,直接卡T了)
(4)a==0&&b==0:
RE的关键所在,因为gcd求出来是0……这个需要认真思考一下,如果c!=0,显然方程不成立,无解;如果c==0,x和y就可以任意取了,由乘法原理可得解的个数就是两个区间内部整数点的个数的乘积
if (c!=0)printf("0\n");
else
{
ll cnt=(q-p+1)*(s-r+1);
printf("%lld\n",cnt);
}
continue;
(5)记得要开long long
两个神坑的数据点:
4
0 1 2 0 0 0 2
1 0 2 0 0 0 0
1 0 2 0 2 0 20
2 0 3 -10 10 -10 10
ans:0 0 0 0
4
0 0 0 -1 1 -1 1
0 0 0 1 -1 1 2
0 0 1 1 1 1 1
0 0 0 -3406792423987599 -23487749 23947250
ans:9 0 0 2753863780940000
#include<iostream> #include<cstdio> using namespace std; long long int x,y; long long int tot=0; long long int a,b,c,p,q,r,s; long long int gcd(long long int a,long long int b) { if(b==0) return a; else return gcd(b,a%b); } long long int exgcd(long long int a,long long int b,long long int & x,long long int & y) { if(b==0) { x=1; y=0; return a; } long long int r=exgcd(b,a%b,x,y); long long int tmp; tmp=x; x=y; y=tmp-a/b*y; return r; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { tot=0; //scanf("%lld %lld %lld %lld %lld %lld %lld",&a,&b,&c,&p,&q,&r,&s); cin>>a>>b>>c>>p>>q>>r>>s; c=-c; if((a==0)&&(y<r||y>s)) { printf("0\n"); continue; } if((b==0)&&(x<p||x>q)) { printf("0\n"); continue; } if(p>q||r>s) { cout<<0<<endl; continue; } int gys=gcd(a,b); if(gys==0) { if (c!=0) { printf("0\n"); continue; } else { tot=(q-p+1)*(s-r+1); printf("%lld\n",tot); continue; } } if(c%gys!=0) { cout<<0<<endl; continue; } exgcd(a,b,x,y); x=x*(c/gys); y=y*(c/gys); a=a/gys; b=b/gys; while(x>=p) { x=x-b; y=y+a; } while(x<p&&b!=0) { x=x+b; y=y-a; } while(x>=p&&x<=q&&y>=r&&y<=s) { tot++; x=x+b; y=y-a; if(x<p||x>q||y<r||y>s) break; } printf("%lld\n",tot); } return 0; }
相关文章推荐
- [codevs1213]解的个数(数论,扩欧)
- codevs1213 解的个数-----------数论/扩展欧几里得
- codevs1213(扩欧,求区间内解的数量)
- 解的个数(codevs 1213)
- Codevs1213 解的个数
- 扩展gcd codevs 1213 解的个数
- [codevs1213]解的个数 二分 + exgcd
- CodeVS 1213 解的个数
- 【CODEVS1258】关路灯
- 一起去打CS(codevs 5059)
- vscode golang开发环境
- 乌龟棋 (codevs 1068)题解
- codevs 2928 你缺什么
- 双栈排序(codevs 1170)题解
- codevs 2800 送外卖(状压dp)
- codevs 1860 最大数
- codevs 1088 神经网络
- VSCode Markdown PDF 导出成 PDF 报 phantomjs binary does not exist 错误的解决办法
- CodeVS 1017 乘积最大
- [洛谷P1631]序列合并/[codevs1245]最小的N个和