zoukankan      html  css  js  c++  java
  • P3811 【模板】乘法逆元

    题目背景

    这是一道模板题

    题目描述

    给定n,p求1~n中所有整数在模p意义下的乘法逆元。

    输入输出格式

    输入格式:

    一行n,p

    输出格式:

    n行,第i行表示i在模p意义下的逆元。

    输入输出样例

    输入样例#1: 复制
    10 13
    输出样例#1: 复制
    1
    7
    9
    10
    8
    11
    2
    5
    3
    4

    说明

    1 leq n leq 3 imes 10 ^ 6, n < p < 200005281n3×106,n<p<20000528

    输入保证 pp 为质数。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    const int N = 3e6 + 10;
    
    #define LL long long
    #define lgj 1000000007
    
    LL jc[N], inv[N], Inv[N];
    LL n, k;
    
    inline LL read(){
        LL x = 0; char c = getchar();
        while(c < '0' || c > '9') c = getchar();
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x;
    }
    
    void exgcd(LL a, LL b, LL & x, LL & y){
        if(!b){
            x = 1;
            y = 0;
            return ;
        }
        exgcd(b, a % b, x, y);
        LL tmp = x;
        x = y;
        y = tmp - a / b * y; 
    }
    
    inline void work_1(){
        LL x, y;
        exgcd((jc[k] * jc[n - k]) % lgj, lgj, x, y);
        while(x < 0) x += lgj;
        LL answer = (jc[n] * x) % lgj;
        printf("%lld", answer);
        exit(0);
    }
    
    inline LL ksm(LL x, LL y){
        LL ret = 1;
        while(y){
            if(y & 1) ret = ret * x % lgj;
            x = x * x % lgj;
            y >>= 1;
        }
        return ret;
    }
    
    inline void work_2(){
        LL x = ksm((jc[k] * jc[n - k]) % lgj, lgj - 2);
        LL answer = (jc[n] * x) % lgj;
        printf("%lld", answer);
        exit(0); 
    }
    
    inline void work_3(){
        inv[1] = inv[0] = 1; Inv[0] = Inv[1] = 1;
        for(int i = 2; i <= n; i ++)
        {
            inv[i] = (1LL * (- (lgj / i)) * inv[lgj % i]) % lgj;
            if(inv[i] < 0) inv[i] += lgj;
            Inv[i] = (Inv[i - 1] % lgj * inv[i] % lgj) % lgj;
            if(Inv[i] < 0) Inv[i] += lgj;
        }    
        LL answer = ((jc[n] % lgj * Inv[k] % lgj) % lgj * Inv[n - k] % lgj) % lgj;
        printf("%lld", answer);
    }
    
    inline void work_4(){
        
        inv[1] = inv[0] = 1;
        for(int i = 2; i <= n; i ++)
        {
            inv[i] = ((1LL * (- (k / i))) * inv[k % i]) % k;    
            if(inv[i] < 0) inv[i] += k;
        } 
    }
    
    int main()
    {
        n = read();
        k = read();
        jc[1] = 1;
        for(int i = 2; i <= n; i ++) jc[i] = (jc[i - 1] * (i % lgj)) % lgj;
        //work_1();//exgcd 
        //work_2();//ksm
        //work_3();//线性求逆元 inv[i] i 在 % lgj 意义下的逆, Inv[i] 阶乘的逆,也就是将逆阶乘
        work_4();
        for(int i = 1; i <= n; i ++) printf("%lld
    ", inv[i]);
        return 0;
    }
  • 相关阅读:
    Set,List,Map,Vector,ArrayList的区别
    关于List,Set,Map能否存储null
    JAVA集合 DelayQueue 的使用 (同步的超时队列)
    FluentScheduler .Net 定时Job
    BeanFactory和FactoryBean
    ansj 分词,超过了标准的 IK 分词.
    Python字典、集合结构详解
    Python列表、元组结构详解
    C语言--结构体&文件
    C语言--指针
  • 原文地址:https://www.cnblogs.com/lyqlyq/p/7794462.html
Copyright © 2011-2022 走看看