51nod 集合计数(拓展欧几里得)
2016-10-04 19:23
225 查看
()
给出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
这道题的意思就是求: i=A*x; N+1-i=B*y; 其实他就A*x+B*y=i+N+1-i->A*x+B*y=N+1 即Ax≡1+N(mod B) 这样子我们可以用拓展欧几里得求出gcd和x。 判断如果gcd(A,B)|(1+N)(整除)的话,那就就是有解,否则的话就是无解,直接输出0. 之后呢,我们要求出最小的非负整数x1,具体怎么求,之前有写过。(对应B的系数为y1) x1就是一个符合的集合数,接着(N-A*x1)/LCM(A,B)即可算出剩下的集合数量。(这里应该很容易理解吧,如样例2, lcm为6,那么每次转移都是(A*x1+6*n)+(B*y1-6*n)=N+1)(n=1,2....(n的取值应该在有效范围)) ps: 令A,B的最小公倍数为lcm,方程在lcm范围内的最小非负整数解是a,则有a+lcm*x<=n,若a!=0那么x即为所求的解得个数 否则x-1即为所求.
#include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cctype> #include<cmath> #include<ctime> #include<string> #include<stack> #include<deque> #include<queue> #include<list> #include<set> #include<map> #include<cstdio> #include<limits.h> #define fir first #define sec second #define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin) #define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout) #define mes(x, m) memset(x, m, sizeof(x)) #define pii pair<int, int> #define Pll pair<ll, ll> #define INF 1e9+7 #define Pi 4.0*atan(1.0) #define MOD 1000000007 #define lowbit(x) (x&(-x)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define ls rt<<1 #define rs rt<<1|1 typedef long long ll; typedef unsigned long long ull; const double eps = 1e-12; const int maxn = 1010; using namespace std; inline int read(){ int x(0),f(1); char ch=getchar(); while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } inline int extend_gcd(ll a, ll b, ll &x, ll &y) { if(0==b){ x=1; y=0; return a; }else{ ll d=extend_gcd(b,a%b,x,y); ll tmp=x; x=y; y=tmp-a/b*x; return d; } } int main() { // fin; ll N, A, B, x, y, d, q; int T; T=read(); while(T--){ scanf("%lld%lld%lld",&N,&A,&B); d=extend_gcd(A,B,x,y); //gcd q=A/d*B; //LCM if((1+N)%d){ printf("0\n"); continue; } else{ int count=0; ll mod=B/d; ll min=((1+N)/d*x%mod+mod)%mod; //最小非负整数 if(min==0){ //会出现0的情况,集合是[1,N]的,所欲这里需要讨论 min=mod; } int res=N-A*min; if(res<0){ printf("0\n"); continue; } else{ count=res/q+1;//+1是min是第一个符合的集合(在范围内[1,N]) } printf("%d\n",count); } } }
相关文章推荐
- 51Nod-集合计数(拓展欧几里得+中国剩余定理)
- 51NOD 1352 集合计数(扩展欧几里得)
- 51nod 1352 集合计数(扩展欧几里得)
- 51nod 1352 集合计数(扩展欧几里得)
- 51nod 1352 集合计数(扩展欧几里德)
- 51nod 1256 乘法逆元 拓展欧几里得求逆元
- 51Nod-1677 treecent(计数)
- 51nod 1616 最小集合(数论)(枚举)
- codeforces 468 B && 51nod 1557 两个集合
- Disgruntled Judge UVA - 12169 (暴力或者拓展欧几里得)
- gcd,欧几里得,拓展欧几里得&NOIP2012d2t1
- 51nod 1610 路径计数(容斥+dp)
- 拓展欧几里得(解同余方程)
- 51Nod-1962-区间计数
- hdu 1576 拓展欧几里得
- SGU 141.Jumping Joe 数论,拓展欧几里得,二元不等式 难度:3
- 51nod-1616 最小集合
- 51NOD 1810 连续区间 分治 区间计数
- 51Nod 1778 小Q的集合
- 拓展集合工具类CollectionUtils