51 Nod 1352 集合计数

来源:互联网 发布:linux c sleep 毫秒 编辑:程序博客网 时间:2024/05/17 23:56

这道很容易就得出一个公式 ax + by = N+1


我们用拓展欧几里得求得他的x极大正值解 和 极小正值解 然后 用 a*(xmax-xmin)/lcm(a,b)+1便是最终答案了


比较需要注意的是边境的处理


#include<iostream>#include<cmath>using namespace std;typedef long long ll;ll ex_gcd(ll a,ll b,ll &x,ll &y){if(b==0){x=1;y=0;return a;}else{ll r = ex_gcd(b,a%b,x,y);ll tmp=x;x = y;y = tmp-a/b*y;return r;}}int main(){//freopen("1352.in","r",stdin);//freopen("1352.out","w",stdout);int t;scanf("%d",&t);while(t--){ll n,a,b;scanf("%lld%lld%lld",&n,&a,&b);n++;ll x,y;ll r = ex_gcd(a,b,x,y);if(n%r) printf("0\n");else{ll lcm = a*b/r;ll times = n/r;x*=times;y*=times;ll aaddition = b/r;ll baddition = a/r;ll xmin=(x%aaddition+aaddition)%aaddition;ll ymax=(n-a*xmin)/b;ll ymin=(y%baddition+baddition)%baddition;ll xmax=(n-ymin*b)/a;//cout << "xmin " << xmin << " ymax " << ymax << endl;//cout << "xmax " << xmax << " ymin " << ymin << endl;if(xmin<=0){xmin+=lcm/a;ymax-=lcm/b;if(ymax<=0){printf("0\n");continue;}}if(ymin<=0){ymin+=lcm/b;xmax-=lcm/a;if(xmax<=0){printf("0\n");continue;}}printf("%lld\n",a*(xmax-xmin)/lcm+1);}}fclose(stdin);    fclose(stdout);}


原创粉丝点击