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为任意整数)
*/

 

posted @ 2017-10-04 13:34  jhz033  阅读(291)  评论(0编辑  收藏  举报