未完全弄懂的题的题51nod1532

Posted 萧魂不散

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了未完全弄懂的题的题51nod1532相关的知识,希望对你有一定的参考价值。

 

转载自:https://blog.csdn.net/luricheng/article/details/52752094
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个。 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 //①
1<=x<=n/a //②
1<=y<=n/b //③
的{x,y}的对数

令:
d=gcd(a,b)
lcm=(x,y)的最小公倍数
x‘=x*(n+1)/d
y‘=y*(n+1)/d
则:
ax‘+by‘= n+1

t1=lcm/a
t2=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_TIME

int 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;
}

以上是关于未完全弄懂的题的题51nod1532的主要内容,如果未能解决你的问题,请参考以下文章

51Nod 1305

51Nod1246 罐子和硬币,不能均分的题

一道有趣的广度优先搜索/动态规划的题

51Nod 算法马拉松21(迎新年)

最近做的题的wp

最近做的题的wp