• 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
     
    #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
    ");
                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
    ",ans);
            }
            else
                printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/10363497.html
Copyright © 2020-2023  润新知