51nod_1352_集合计数 (exgcd)

题意:ax+by=n+1,x>0,y>0的解的个数

先判断(a,b)是否整除n+1,不整除无解,有解后用exgcd算出一解(x1,y1),

然后在草稿纸上写下x1+d*(b/gcd(a,b))>0,  y1-d*(b/gcd(a,b))>0,算出d的范围,大于号一侧向下取整(若本身为整数,还要-1,因为取不到等号),小于相反。

注意 : 负数时,取整是变大,正数是变小。

#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cstdlib>
#define getrand(a,b) (int)((rand()/33000.0)*((b)-(a)+1))+(a)
using namespace std;
typedef long long LL;
const int maxnn=100+5;
const int maxn=100000+5;
const int mod=1e9+7;
int gcd(LL a,LL b){
    if(b==0)return (int)a;
    else return gcd(b,a%b);
}
void exgcd(LL a,LL b,LL& x,LL& y,LL g){
    if(a==g){
        x=1;
        y=0;
        return;
    }
    exgcd(b,a%b,y,x,g);
    y-=(a/b)*x;
}
int main()
{
    LL t,n,a,b,g,x,y,k,d1,d2;
    cin>>t;
    while(t--){
        cin>>n>>a>>b;
        g=gcd(a,b);
        if((n+1)%g){
            cout<<0<<endl;
            continue;
        }
        if(a<b) swap(a,b);
        exgcd(a,b,x,y,g);
        k=(n+1)/g;
        x*=k;y*=k;
        if(a*x+b*y==0)cout<<0<<endl;
        else if(a*x+b*y>0){
            d1=(-x*g)/b;
            if(-x*g==d1*b||-x*g>=0)d1++;
            d2=(y*g)/a;
            if(a*d2==y*g||y*g<=0)d2--;
            cout<<d2-d1+1<<endl;
        }
        else{
            d2=(-x*g)/b;
            if(b*d2==-x*g||-x*g<=0)d2--;
            d1=(y*g)/a;
            if(d1*a==y*g||y*g>=0)d1++;
            cout<<d2-d1+1<<endl;
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/Gsimt/p/8394666.html

时间: 2024-11-09 12:50:07

51nod_1352_集合计数 (exgcd)的相关文章

【BZOJ2839】集合计数 组合数+容斥

[BZOJ2839]集合计数 Description 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得它们的交集的元素个数为K,求取法的方案数,答案模1000000007.(是质数喔~) Input 一行两个整数N,K Output 一行为答案. Sample Input 3 2 Sample Output 6 HINT [样例说明]假设原集合为{A,B,C}则满足条件的方案为:{AB,ABC},{AC,ABC},{BC,ABC},{AB

51nod 1352:集合计数

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

bzoj2839 集合计数

2839: 集合计数 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 243  Solved: 129 [Submit][Status][Discuss] Description 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得 它们的交集的元素个数为K,求取法的方案数,答案模1000000007.(是质数喔~) Input 一行两个整数N,K Output 一行为答案. Sample I

bzoj2839 集合计数(容斥)

2839: 集合计数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 883  Solved: 490[Submit][Status][Discuss] Description 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得 它们的交集的元素个数为K,求取法的方案数,答案模1000000007.(是质数喔~) Input 一行两个整数N,K Output 一行为答案. Sample Inp

51nod 1352 集合计数(扩展欧几里得)

题目链接:传送门 题意:略 分析: 非常easy能够得到一个方程 A*x + B*y = N + 1 这式子能够用扩展GCD求出gcd,x和y,然后我们求出大于0的最小x,A*x第一个满足条件的集合firstSet,剩下的N-firstSet个集合能够直接除LCM(A,B)(A和B的最小公倍数)统计出数量. 代码例如以下: #include <stdio.h> #include <string.h> #include <iostream> #define LL long

51nod 1352 集合计数

给出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

hdu 6092 Rikka with Subset (集合计数,01背包)

Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them: Yuta has n positive A1?An and their sum is m. Then for each subset S of A, Yuta calcula

BZOJ 2839 集合计数 容斥原理

题目大意:给定n个元素,求交集大小为k的集合的集合共有多少种 考虑容斥原理 计算交集大小至少为i的集合有多少种 首先需要选出i个元素 方案为C(n,i) 其它2^(n-i)个集合每个可选可不选 一共2^[2^(n-i)]种 故答案为Σ[k<=i<=n]C(n,i)C(i,k)*2^[2^(n-i)] #include <cstdio> #include <cstring> #include <iostream> #include <algorithm&

51 Nod 1352 集合计数(中国剩余定理+扩展欧几里得)

题目链接:点我点我 题意:中文题 题解:由题意我们可以构造出方程:Ax+By=N+1,用扩展欧几里得算出最小的非负整数解x(x确定,y也就确定了),然后再把剩余的数分配掉(以它们的最小公倍数去分). 1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 6 typedef long long LL; 7 8 LL e_gcd(LL a,LL b,