A+B | ||
Accepted : 8 | Submit : 77 | |
Time Limit : 1000 MS | Memory Limit : 65536 KB |
题目描述给你三个整数a,b,n。问有多少种只包含a,b的不同序列,使得这个序列的和为n。 例如a=2,b=3,n=7,那么有一种序列:(2+2+3=7,2+3+2=7,3+2+2=7)这三种看作相同,算一种。 例如a=3,b=3,n=6,那么只有一种序列:3+3=6。 例如a=4,b=5,n=7,那么不管a和b怎么排都不会等于7,那么就只有0种序列。 输入多个样例,每个样例占一行,包括3个整数a,b,n。(0< a,b,n <10^9).直到文件结束。 输出每个样例输出一行,一个整数,为a,b所能排出的序列数。 样例输入2 3 7 3 3 6 4 5 7 样例输出1 1 0 |
题目意思就不说了,中文题目。
看到这个就想到了扩展欧几里得,不过手搓,没写出来,然后就找了以前自己写的扩展欧几里得模板。
没学过扩展欧几里得算法的可以看下http://blog.sina.com.cn/s/blog_61c7e64d0100kwna.html 科普下。
利用扩展欧几里得可以解出ax+by=1的一个解,
现在的x,y是ax+by=1的一个解,
x=x*s,y=y*s; 同时扩大s倍,
现在的xy是ax+by=s的一个解。
现在的xy是ax+by=s的一个解。
因为ax+by=s,所以a(x+nb)+b(y-na)=s也是可行解。
进而可以把ax+by=s通解找到。
由于这个题目要使得解都是正数或0,(0也可以,这点是大坑。。。要不是晓东当时问了一句c题是不是a和b不一定要有,当时都不知道问题所在。)还有就是a==b需要特判。
AC代码:
//a和b不一定要有,fuck!!!
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
//不用int64就可以A的
__int64 exgcd(__int64 a,__int64 b,__int64 &x,__int64 &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
__int64 g=exgcd(b,a%b,x,y);
__int64 temp=x;
x=y;
y=temp-(a/b)*y;
return g;
}
__int64 gcd(__int64 m,__int64 n)
{
while(n)
{
__int64 tmp=m%n;
m=n;
n=tmp;
}
return m;
}
__int64 mi(__int64 m,__int64 n)
{
if(m>n) return n;
return m;
}
__int64 ma(__int64 m,__int64 n)
{
if(m>n) return m;
return n;
}
int main()
{
__int64 a,b,s,d;
while(~scanf("%I64d%I64d%I64d",&a,&b,&s))
{
__int64 x,y;
d=gcd(a,b);
if(s%d!=0)
{
puts("0");
continue;
}
else if(a+b>s)
{
puts("0");
continue;
}
else if(a==b)
{
if(s%a==0)
puts("1");
else puts("0");
continue;
}
a=a/d,b=b/d,s=s/d;
__int64 tt=exgcd(a,b,x,y);
//现在的x,y是ax+by=1的一个解
x=x*s,y=y*s;
//现在的xy是ax+by=s的一个解
__int64 cnt=0;
//__int64 s1,s2;
//根据x,y的值来判断到底有多少可行解
//因为ax+by=s,所以a(x+nb)+b(y-na)=s也是可行解,所以直接找n的值使得x+nb与y-na都为正数或0即可
//代码写搓了。。
/*if(x<=0&&y>=0) //okok
{
x=-x;
if(x%b==0) s1=x/b;
else s1=x/b+1;
if(y%a==0) s2=y/a;
else s2=y/a;
}
else if(y<=0&&x>=0) //okok
{
y=-y;
if(y%a==0) s1=y/a;
else s1=y/a+1;
if(x%b==0) s2=x/b;
else s2=x/b;
}
else if(x>0&&y>0) //ok
{
s1=-x/b;
s2=x/b;
s1=ma(s1,-y/a);
s2=mi(s2,y/a);
}
else
{
puts("0");
continue;
}*/
x=x%b;
if(x<0) x+=b;
y=(s-a*x)/b; //解出a(x+nb)+b(y-na)=s,n=0时候的值
if(y<0) cnt=0;
else cnt=y/a+1;
printf("%I64d\n",cnt);
}
return 0;
}
感谢cc_again......