51nod 1352 集合计数 扩展欧几里得
基准时间限制:1 秒 空间限制:131072 KB
给出N个固定集合{1,N},{2,N-1},{3,N-2},...,{N-1,2},{N,1}.求出有多少个集合满足:第一个元素是A的倍数且第二个元素是B的倍数。
提示:
对于第二组测试数据,集合分别是:{1,10},{2,9},{3,8},{4,7},{5,6},{6,5},{7,4},{8,3},{9,2},{10,1}.满足条件的是第2个和第8个。
Input
第1行:1个整数T(1<=T<=50000),表示有多少组测试数据。 第2 - T+1行:每行三个整数N,A,B(1<=N,A,B<=2147483647)
Output
对于每组测试数据输出一个数表示满足条件的集合的数量,占一行。
Input示例
2 5 2 4 10 2 3
Output示例
1 2
AX+BY=N+1;
解方程;
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cmath> #include<string> #include<queue> #include<algorithm> #include<stack> #include<cstring> #include<vector> #include<list> #include<bitset> #include<set> #include<map> #include<time.h> using namespace std; #define LL long long #define bug(x) cout<<"bug"<<x<<endl; const int N=1e5+10,M=1e6+10,inf=1e9+10,MOD=1e9+7; const LL INF=1e18+10,mod=1e9+7; const double eps=(1e-8),pi=(4*atan(1.0)); void exgcd(LL a, LL b, LL &x, LL &y) { if(b == 0) { x = 1; y = 0; return; } exgcd(b, a % b, x, y); LL tmp = x; x = y; y = tmp - (a / b) * y; } int main() { int T; scanf("%d",&T); while(T--) { LL n,a,b; scanf("%lld%lld%lld",&n,&a,&b); LL x,y; LL gc=__gcd(a,b); a/=gc; b/=gc; exgcd(a,b,x,y); n++; if(n%gc==0) { n/=gc;x*=n;y*=n; LL xx=(x-(x/b)*b); LL yy=(y+(x/b)*a); if(xx<=0)xx+=b,yy-=a; //cout<<xx<<" "<<yy<<endl; if(xx>n||yy<0)printf("0\n"); else printf("%lld\n",min((n-xx)/b+1,yy/a+((yy%a)?1:0))); } else printf("0\n"); } return 0; } /* p = p0 + b/Gcd(a, b) * t q = q0 - a/Gcd(a, b) * t(其中t为任意整数) */