zoukankan      html  css  js  c++  java
  • Unknown Treasure---hdu5446(卢卡斯+中国剩余定理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5446

    C(n, m) % (p1*p2*p3*...*pk)的值

    其实这个就是中国剩余定理最后算出结果后的最后一步求余

    那C(n, m)相当于以前我们需要用中国剩余定理求的值

    然而C(n, m)太大,我们只好先算出

    C(n, m) % p1 = r1

    C(n, m) % p2 = r2

    C(n, m) % p3 = r3

    .

    .

    .

    C(n, m) % pk = rk

    用Lucas,这些r1,r2,r3...rk可以算出来

    然后用中国剩余定理求满足num%p[i]=r[i]的最小num即可,num既是所求答案;

    注意在运算过程中会出现数相乘爆long long,所以要手动写乘法求余;

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <stack>
    #include <math.h>
    
    using namespace std;
    
    #define met(a, b) memset(a, b, sizeof(a))
    #define N 153
    #define INF 0x3f3f3f3f
    
    typedef long long LL;
    
    ///快速幂计算a*b%p,因为a*b直接相乘可能会爆LL;
    LL Mul(LL a, LL b, LL p)
    {
        a = (a+p)%p;
        b = (b+p)%p;
        LL ans = 0;
        while(b)
        {
            if(b%2)
                ans = (ans+a)%p;
            a=(a+a)%p;
            b/=2;
        }
        return ans;
    }
    
    ///用快速幂求a^b%p;
    LL quick_mod(LL a, LL b, LL p)
    {
        LL ans = 1;
        a %= p;
        while(b)
        {
            if(b&1)
            {
                ans = ans*a%p;
                b--;
            }
            b = b/2;
            a = a*a%p;
        }
        return ans;
    }
    ///求C(n, m)%p;
    LL C(LL n, LL m, LL p)
    {
        if(m > n)return 0;
        LL ans = 1;
        for(int i=1; i<=m; i++)
        {
            LL a = (n+i-m)%p;
            LL b = i%p;
            ans = ans*(a*quick_mod(b, p-2, p)%p)%p;
        }
        return ans;
    }
    ///卢卡斯用于求C(n, m)%p;
    LL Lucas(LL n, LL m, LL p)
    {
        if(m == 0)return 1;
        return C(n%p, m%p, p) * Lucas(n/p, m/p, p)%p;
    }
    ///扩展欧几里德 求ax+by = gcd(a, b)中的x和y
    void ex_gcd(LL a, LL b, LL &x, LL &y)
    {
        if(b == 0)
        {
            x = 1;
            y = 0;
            return;
        }
        ex_gcd(b, a%b, x, y);
        int t = x;
        x = y;
        y = t - a/b*y;
        if( a*b < 0 )///当ab异号时;
        {
            x = -x;
            y = -y;
        }
    }
    ///已知 num%p[i]=r[i];求满足n个式子的最小num,其中p[i]是素数;
    LL China(int n, LL p[], LL r[])
    {
        LL m = 1, num = 0;
        for(int i=1; i<=n; i++)
            m *= p[i];
        for(int i=1; i<=n; i++)
        {
            LL x, y, a = m/p[i], b = -p[i];
            ex_gcd(a, b, x, y);
            LL t = Mul(a, x, m);///Mul就是乘法,防止爆longlong;
            num = (num + Mul(t, r[i], m) + m) % m;
        }
        return (num+m)%m;
    }
    
    int main()
    {
        LL n, m;
        int k, T;
        scanf("%d", &T);
        while(T--)
        {
            LL p[15], r[15];
            scanf("%I64d %I64d %d", &n, &m, &k);
            for(int i=1; i<=k; i++)
            {
                scanf("%I64d", &p[i]);
                r[i] = Lucas(n, m, p[i]);
            }
            printf("%I64d
    ", China(k, p, r));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    chrome扩展及应用开发 李喆pdf完整版
    Chrome插件(扩展)开发资料
    Fiddler下载地址
    如果没有 Android 世界会是什么样子?
    一张图告诉你:Android系统哪代强?
    Android开发的16条小经验总结
    Android上实现MVP模式的途径
    Android事件总线还能怎么玩?
    Android性能优化典范(二)
    安卓listView实现下拉刷新上拉加载滑动仿QQ的删除功能
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5511356.html
Copyright © 2011-2022 走看看