hdu1573-X问题-(扩展欧几里得定理+中国剩余定理)

X问题

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8416    Accepted Submission(s):
3066

Problem Description

求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X mod a[1] =
b[1], X mod a[2] = b[2], …, X mod a[i] = b[i], … (0 < a[i] <= 10)。

Input

输入数据的第一行为一个正整数T,表示有T组测试数据。每组测试数据的第一行为两个正整数N,M (0 < N
<= 1000,000,000 , 0 < M <=
10),表示X小于等于N,数组a和b中各有M个元素。接下来两行,每行各有M个正整数,分别为a和b中的元素。

Output

对应每一组输入,在独立一行中输出一个正整数,表示满足条件的X的个数。

Sample Input

3
10 3
1 2 3
0 1 2
100 7
3 4 5 6 7 8 9
1 2 3 4 5 6 7
10000 10
1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9

Sample Output

1
0
3

中国剩余定理(https://www.cnblogs.com/zwfymqz/p/8425731.html)

#include <iostream>
#include<stdio.h>
#include <algorithm>
#include<string.h>
#include<cstring>
#include<math.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;

int a[15];
int r[15];
int n,m,x,y;
int lcm;
int gcd;

int exgcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int q=exgcd(b,a%b,y,x);
    y=y-(a/b)*x;
    return q;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        bool flag=true;
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<m;i++)
            scanf("%d",&r[i]);
        int a1=a[0];
        int r1=r[0];

        for(int i=1;i<m;i++)
        {
            //printf("facai\n");
            int b1=a[i];
            int r2=r[i];
            gcd=exgcd(a1,b1,x,y);
            int d=r2-r1;
            if(d%gcd)//无解
                {flag=false;break;}
            int multiple=d/gcd;
            int p=b1/gcd;
            x=( (x*multiple)%p+p )%p;//最小正数解
            r1=x*a1+r1;//合并后更新余数
            a1=a1*b1/gcd;//更新除数为两者的最小公倍数
        }
        ///联立完所有的式子后,a1=lcm,r1也是终极余数
        ///求满足的k的数量 0<r1+lcm*k<=n
        ///k=(n-r1)/lcm ,  但是当r1=0时,k=0不能算进答案
        if(r1 > n) flag = false;
        int ans=0;
        if(flag)
        {
            ans=1+(n-r1)/a1;///k=0也算一个
            if(ans && r1==0) ans--;///ans至少要有一个才能自减,不然可能变成-1了
            printf("%d\n",ans);
        }
        else
            printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/shoulinniao/p/10363497.html

时间: 2024-08-01 21:27:24

hdu1573-X问题-(扩展欧几里得定理+中国剩余定理)的相关文章

hdu3579-Hello Kiki-(扩展欧几里得定理+中国剩余定理)

Hello Kiki Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5489    Accepted Submission(s): 2164 Problem Description One day I was shopping in the supermarket. There was a cashier counting coins

扩展欧几里得定理

扩展欧几里得定理,很早之前就接触过,没看懂,放弃了,前些天有个有一个题,用扩展欧几里得定理,我竟然都不知道.决定看一下. 看扩展欧几里得定理的最好地方是用维基百科搜索扩展欧几里得算法 就能搜到 照着上面提供第例子走一遍知道什么意思了. 反正主要就是 ax+by=1(mod n) 的x,y值: 还有就是 ax=b(mod n) 这类题的通用解法: 下面粘上一个例子,看完这个例子你就明白了. poj 1061 青蛙的约会 中文题目,我的最爱. 我们设他们跳的步数为step 那么就可以写出算式 n*s

HDU 2669 Romantic (扩展欧几里得定理)

题目大意:给两个数a和b,找出一组x,y使得a*x + b*y = 1,如果找不出输出sorry   题解:显然是用扩展欧几里得定理求解. 又扩展欧几里得定理有,如果a*x+b*y = d   要使得方程有解必有gcd(a,b)为d的约数. 而此题的d = 1  所以若gcd(a,b)!=1,则应该输出sorry #include <bits/stdc++.h> using namespace std; long long e_gcd(long long a,long long b,long

poj1061-青蛙的约会-(贝祖定理+扩展欧几里得定理+同余定理)

青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions:132162   Accepted: 29199 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能

扩展欧几里得定理总结

拓展欧几里得定理主要用来求解同余线性方程,求逆元等,遇到题目给出形如ax+by==c,要求一组满足要求的x和y时,可以联系扩展欧几里得求解 拓展欧几里得由 gcd(a,b) = gcd(b,a%b) 推出 由于 a*x + b*y == gcd(a,b) 必定有解 所以 b*x + (a%b)*y == gcd(b,a%b) 最终得到ax+by==a*y1+b*(x1-(a/b)*y1) 当x0 y0 是方程的一组解,可以得到所有解的形式满足 x=x0+b/d*t y=y0-a/d*t 当 题目

扩展欧几里得定理——POJ 1061

对应POJ 题目:点击打开链接 青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 94409   Accepted: 17470 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得

扩展欧几里得定理基础讲解 代码及证明

知识储备 1 . 朴素欧几里得原理:gcd(a,b) == gcd(b,a % b) 2 . 负数取模:忽略符号返回绝对值就好了 3 . 模数原理:对于整数a,b必然存在整数k使得a % b == a - k * b, 且此时k == a / b向下取整 定理内容 对于正整数a,b,必然存在整数(不一定是正数)x,y, 使得ax+by==gcd(x,y) 证明 (来自SDFZ-SPLI的援助) 把两边同时除以gcd(x,y),由朴素欧几里得定理可以得到恒等式,说明一定存在至少一组解使得$ax+b

CSU 1446 Modified LCS 扩展欧几里得

要死了,这个题竟然做了两天……各种奇葩的错误…… HNU的12831也是这个题. 题意: 给你两个等差数列,求这两个数列的公共元素的数量. 每个数列按照以下格式给出: N F D(分别表示每个数列的长度,首项,公差). 思路: 先用扩展欧几里得得到两个数列的一个交点,然后求出两个数列的第一个交点.然后分别得到从第一个交点,到末项的可能交点数量. 假设 F1+K1*D1 = F2+K2*D2 是某一个交点, 移向得到 F1 - F2 = K2*D2 - K1*D1. 由扩展欧几里得定理的结论 x*

exgcd扩展欧几里得求解的个数

知识储备 扩展欧几里得定理 欧几里得定理 (未掌握的话请移步[扩展欧几里得]) 正题 设存在ax+by=gcd(a,b),求x,y.我们已经知道了用扩欧求解的方法是递归,终止条件是x==1,y==0: int exgcd( int a, int b, int &x, int &y ) { if( b == 0 ) { x = 1; y = 0; return a; } int tmp = a % b; if( tmp > b ) swap( tmp, b ); int ans=exg