题意: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; }