51NOD 1352 集合计数 拓展欧几里得

来源:互联网 发布:画设计图的软件 编辑:程序博客网 时间:2024/05/18 02:33
1352 集合计数基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题收藏关注给出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个。Input1行:1个整数T(1<=T<=50000),表示有多少组测试数据。第2 - T+1行:每行三个整数N,A,B(1<=N,A,B<=2147483647)Output对于每组测试数据输出一个数表示满足条件的集合的数量,占一行。Input示例25 2 410 2 3Output示例12
问题其实就是求满足ax+by=n+1 //①1<=x<=n/a //②1<=y<=n/b //③的{x,y}的对数令:d=gcd(a,b)lcm=(x,y)的最小公倍数x'=x*(n+1)/dy'=y*(n+1)/d:ax'+by'= n+1t1=lcm/at2=lcm/b显然:a(x'+k*t1) + b(y'-k*t2)=n+1 a(x'-k*t1) + b(y'+k*t2)=n+1        k=0,1,2...只要找到第一对满足①②③的x,y 然后根据Lcm就可以找到一共有多少对
#include<iostream>#include<stdlib.h>#include<stdio.h>#include<string>#include<vector>#include<deque>#include<queue>#include<algorithm>#include<set>#include<map>#include<stack>#include<time.h>#include<math.h>#include<list>#include<cstring>#include<fstream>//#include<memory.h>using namespace std;#define ll long long#define ull unsigned long long#define pii pair<int,int>#define INF 1000000007#define pll pair<ll,ll>#define pid pair<int,double>//#define CHECK_TIMEint extend_gcd(ll a,ll b,ll&x,ll&y){    if(!b){        x=1;        y=0;        return a;    }    ll xt=0,yt=0;    int d=extend_gcd(b,a%b,xt,yt);    x=yt;    y=xt-yt*(a/b);    return d;}int main(){    int T;    scanf("%d",&T);    ll n,a,b,x,y,d,lcm,t1,t2;    while(T--){        scanf("%lld%lld%lld",&n,&a,&b);        d=extend_gcd(a,b,x,y);        if((n+1)%d!=0){            printf("0\n");            continue;        }        x*=(n+1)/d,y*=(n+1)/d;        lcm=a/d*b;        t1=lcm/a,t2=lcm/b;        if(x<1){            ll num=(1-x)/t1;            x+=num*t1;            y-=num*t2;            if(x<1){                y-=t2;                x+=t1;            }        }        if(y<1){            ll num=(1-y)/t2;            y+=num*t2;            x-=num*t1;            if(y<1){                y+=t2;                x-=t1;            }        }        int ans=x>0&&y>0;        if(ans){            ans+=min((x-1)/t1,(n/b-y)/t2);            ans+=min((y-1)/t2,(n/a-x)/t1);        }        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击