湘潭大學四月月賽C題A+B(擴充套件歐幾里得定理)

果7發表於2014-04-14

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的一個解
因為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......

相關文章