hdu - 3049 - Data Processing(乘法逆元)

题意:N(N<=40000)个数n1, n2, ..., nN (ni<=N),求(2 ^ n1 + 2 ^ n2 + ... + 2 ^nN) / N % 1000003。

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

——>>RJ白书上说“由于‘乘法逆’太重要了……”,上一年南京区赛同学也碰到了求逆元……现在,学习了。。

什么是乘法逆?ab % m = 1 (这里的 a, b 分别都是模 m 的同余等价类),a 模 m 的乘法逆是 b,同时,b 模 m 的乘法逆是a。

乘法逆有什么用?这个用处可还真不小。。如果要求 a / b % m(保证 b | a),但是 a 很大很大,比如 a = 2 ^ 40000,这个式子可不等价于 (a % m) / (b % m) % m。。这时,乘法逆就可以上场了。。一个数除以 b 后模 m,等价于该数乘以 b 模 m 的乘法逆后模 m。。于是上式可变成 a * b的乘法逆 % m,这就容易多了,就是
(a % m) * (b的乘法逆 % m) % m。。

怎么求乘法逆?要求 a 模 m 的乘法逆,设其为 x,因为 a * x % m = 1,所以 a * x + m * y = 1。。这是什么,一元二次方程,于是乎,扩展欧几里得飞一下就出来了。。

#include <cstdio>

typedef long long LL;

const int MOD = 1000003;
const int MAXN = 40000 + 10;

int N, kase;
LL sum;
int pow2[MAXN];

void GetPow2()
{
    pow2[0] = 1;
    for (int i = 1; i < MAXN; ++i)
    {
        pow2[i] = (pow2[i - 1] << 1) % MOD;
    }
}

void Read()
{
    int n;

    sum = 0;
    scanf("%d", &N);
    for (int i = 0; i < N; ++i)
    {
        scanf("%d", &n);
        sum = (sum + pow2[n]) % MOD;
    }
}

void gcd(LL a, LL b, LL& d, LL& x, LL& y)
{
    if (!b)
    {
        d = a;
        x = 1;
        y = 0;
        return;
    }
    else
    {
        gcd(b, a % b, d, y, x);
        y -= a / b * x;
    }
}

LL Inv(int a, int n)
{
    LL ret, d, y;

    gcd(a, n, d, ret, y);

    return d == 1 ? (ret + n) % n : -1;
}

void Solve()
{
    LL ret;
    LL inv = Inv(N, MOD);
    ret = sum * inv % MOD;
    printf("Case %d:%I64d\n", ++kase, ret);
}

int main()
{
    int T;

    kase = 0;
    GetPow2();
    scanf("%d", &T);
    while (T--)
    {
        Read();
        Solve();
    }

    return 0;
}
时间: 2024-09-30 06:18:41

hdu - 3049 - Data Processing(乘法逆元)的相关文章

HDU 3049 Data Processing 数论题解

Problem Description Chinachen is a football fanatic, and his favorite football club is Juventus fc. In order to buy a ticket of Juv, he finds a part-time job in Professor Qu's lab. And now, Chinachen have received an arduous task--Data Processing. Th

HDU 1452 (约数和+乘法逆元)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1452 题目大意:求2004^X所有约数和,结果mod 29. 解题思路: ①整数唯一分解定理: 一个整数A一定能被分成:A=(P1^K1)*(P2^K2)*(P3^K3).....*(Pn^Kn)的形式.其中Pn为素数. 如2004=(22)*3*167. 那么2004x=(22x)*(3x)*(167x). ②约数和公式 对于一个已经被分解的整数A=(P1^K1)*(P2^K2)*(P3^K3)

HDU 1576 (乘法逆元)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1576 题目大意:求(A/B)mod 9973.但是给出的A是mod形式n,n=A%9973. 解题思路: 两种思路,一种从乘法逆元角度,另一种从扩展GCD推公式角度. ①乘法逆元: 先来看下逆元和乘法逆元的关系,对于A*X=B,有X=A-1*B,A-1就是普通的逆元了,在这里就是倒数. 如果A*X=B mod n,变成同余式了,那么A-1依然是存在的,只不过不是倒数了,一般把同余之后的逆元称为乘法

HDU 1576 -- A/B (总结乘法逆元的几种求法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576 A/B Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7264    Accepted Submission(s): 5774 Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%99

hdu 1452 Happy 2004 (快速幂+取模乘法逆元)

Problem Description Consider a positive integer X,and let S be the sum of all positive integer divisors of 2004^X. Your job is to determine S modulo 29 (the rest of the division of S by 29).Take X = 1 for an example. The positive integer divisors of

HDU 4828 Grids(卡特兰数+乘法逆元)

首先我按着我的理解说一下它为什么是卡特兰数,首先卡特兰数有一个很典型的应用就是求1~N个自然数出栈情况的种类数.而这里正好就对应了这种情况.我们要满足题目中给的条件,数字应该是从小到大放置的,1肯定在左上角,所以1入栈,这时候我们放2,如果我们把2放在了1的下面就代表了1出栈,把2放在上面就代表了2也进栈(可以看一下hint中第二组样例提示),以此类推,这样去放数,正好就对应了上面一行入栈,下面一行出栈的情况,一共n行,对应上限为n的卡特兰数. 需要注意的地方就是在使用卡特兰数递推式的时候,除法

LightOJ - 1050 (唯一分解+推公式+乘法逆元)

题意:求a^b的所有约数和对1e9+7取模的结果 思路:对于一个数p,进行唯一分解,则p=P1^M1*P2^M2*...*Pn^Mn,则p的所有约数之和等于(P1^0+P1^1+...+P1^M1)*(P2^0+P2^1+...+P2^M2)*...*(Pn^0+Pn^1+...+Pn^Mn), p^t=P1^(M1*t)*P2^(M2*t)*...*Pn^(Mn*t),每一个(Pn^0+Pn^1+...+Pn^Mn)利用等比数列可以直接推出公式为(Pn^(Mn*t+1)-1)/(Pn-1),用

POJ1845 Sumdiv - 乘法逆元+快速幂【A^B的约数个数和】

POJ1845 Sumdiv Sol: 约数个数和\(sumdiv=(1+p_1+p_1^2+\dots + p_1^{c_1})*\dots *(1+p_k+p_k^2+\dots + p_k^{c_k})\) 其中每一项都是一个首项为1,公比为\(p_i\)的等比数列的和,即 \(1*\frac{1-p_i^{c_{k}+1}}{1-p_i}=\frac{p_i^{c_{k}+1}-1}{p_i-1}\) 可以通过快速幂+逆元求解. 然而,当\(9901|(p_i-1)\)时,\(p_i-1

HDU3037 Saving Beans(Lucas定理+乘法逆元)

题目大概问小于等于m个的物品放到n个地方有几种方法. 即解这个n元一次方程的非负整数解的个数$x_1+x_2+x_3+\dots+x_n=y$,其中0<=y<=m. 这个方程的非负整数解个数是个经典问题,可以+1转化正整数解的个数用插板法解决:$C_{y+n-1}^{n-1}=C_{y+n-1}^y$. 而0<=y<=m,最后的结果就是—— $$\sum_{i=0}^m C_{i+n-1}^i$$ $$C_{n-1}^0+C_{n}^1+C_{n+1}^2+\dots+C_{n-1