1. 程式人生 > >51nod_1352_集合計數 (exgcd)

51nod_1352_集合計數 (exgcd)

pan div 大於 main 大於號 ret out define str

題意: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)