码迷,mamicode.com
首页 > 其他好文 > 详细

51nod_1352_集合计数 (exgcd)

时间:2018-01-31 22:03:51      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:集合   clu   mes   while   gpo   大于   rand   a*   pac   

题意:ax+by=n+1,x>0,y>0的解的个数

先判断(a,b)是否整除n+1,不整除无解,有解后用exgcd算出一解(x1,y1),

然后在草稿纸上写下x1+d*(b/gcd(a,b))>0,  y1-d*(b/gcd(a,b))>0,算出d的范围,大于号一侧向下取整(若本身为整数,还要-1,因为取不到等号),小于相反。

注意 : 负数时,取整是变大,正数是变小。

#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cstdlib>
#define getrand(a,b) (int)((rand()/33000.0)*((b)-(a)+1))+(a)
using namespace std;
typedef long long LL;
const int maxnn=100+5;
const int maxn=100000+5;
const int mod=1e9+7;
int gcd(LL a,LL b){
    if(b==0)return (int)a;
    else return gcd(b,a%b);
}
void exgcd(LL a,LL b,LL& x,LL& y,LL g){
    if(a==g){
        x=1;
        y=0;
        return;
    }
    exgcd(b,a%b,y,x,g);
    y-=(a/b)*x;
} 
int main()
{
    LL t,n,a,b,g,x,y,k,d1,d2;
    cin>>t;
    while(t--){
        cin>>n>>a>>b;
        g=gcd(a,b);
        if((n+1)%g){
            cout<<0<<endl;
            continue;
        } 
        if(a<b) swap(a,b);
        exgcd(a,b,x,y,g);
        k=(n+1)/g;
        x*=k;y*=k;
        if(a*x+b*y==0)cout<<0<<endl;
        else if(a*x+b*y>0){
            d1=(-x*g)/b;
            if(-x*g==d1*b||-x*g>=0)d1++;
            d2=(y*g)/a;
            if(a*d2==y*g||y*g<=0)d2--;
            cout<<d2-d1+1<<endl;
        }
        else{
            d2=(-x*g)/b;
            if(b*d2==-x*g||-x*g<=0)d2--;
            d1=(y*g)/a;
            if(d1*a==y*g||y*g>=0)d1++;
            cout<<d2-d1+1<<endl;
        }    
    }

    return 0;
}

 

51nod_1352_集合计数 (exgcd)

标签:集合   clu   mes   while   gpo   大于   rand   a*   pac   

原文地址:https://www.cnblogs.com/Gsimt/p/8394666.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!