CF896D Nephren Lance un cinéma (composition + numéro de comptage théorie)

Lien CF896D Nephren Runs Cinéma

Grand Ainai Fu Lin. . . .

Personnellement , je pense que ce problème et P3266 [JLOI2015] ne me mens pas un peu.
Tout d' abord, considérer dp, \ (f [i] [j] \) est dirigé vers la première personne i, j programme courant feuilles restantes de 50 dollars, l' équation de transfert est clair, aussi apparemment délai d' attente.

Inspirée P3266, en prenant dans les deux dimensions système de coordonnées, coordonnées x représente en déroute qui, coordonnée y représente le nombre des 50 dollars restants, ne sont pas considérés utilisateur vip, en supposant que le dernier reste de p 50 dollars, le programme est le nombre de (, (00) \) \ juste sous la partie supérieure droite ou de droite \ ((n, P) \) est le nombre de programmes, à l' étape n, le nombre d'étapes haut - bas le nombre de pas = p , le nombre d'étapes vers le haut nombre d'étapes vers le bas + = n, le nombre de programmes disponibles pour résoudre pour \ (n-C_ {} ^ {(n-- P) / 2} \) , dans lequel le nombre a un programme illégal, à savoir, contact la ligne droite \ (y = -1 \) chemin, il faut soustraire de \ ((0, -2) \) à ((n, p) \) \  nombre de programmes, à savoir \ (C_ {n} ^ {(n-- P) / 2 -. 1} \) . Enfin, parce que le l et r est continue, donc tout ce que nous pouvons éliminer l' expression calculée en ajoutant le terme intermédiaire, et enfin que \ (C_ {n} ^ { (n - l) / 2} - C_ {n} {^ (n-- R & lt -. 1) / 2} \) , vip nous avons besoin d'énumérer le nombre d'utilisateurs, alors que la plupart du nombre total compté en soustrayant le nombre de vip, obtenu en multipliant le résultat par \ (C_ {n} ^ { i} \) (i est le nombre de vip).

Parce que le module est pas un nombre premier, non pas avec le petit théorème de Maria, ne trouve pas aussi avec inverse exgcd, donc nous modulo p décomposition premier facteur, dans la pré-factoriel, lorsque les principaux facteurs p contient retiré, rappelez - vous sous l' index, puis le reprendre. Compter directement inverse le théorème d'Euler.
code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long lld;
const int N = 100005;
lld p, n, l, r;
lld pr[N], inv[N], f[N], c[N][40], phi;
//pr[]为p的质因子,c[i][j]为i的阶乘中p的第j个质因子的指数
int cnt = 0;
lld powe(lld a, lld b) {
    lld base = 1;
    while(b) {
        if(b & 1) base = (base * a) % p;
        a = (a * a) % p;
        b >>= 1;
    }
    return base;
}
void calc() {
    f[0] = inv[0] = 1;
    f[1] = inv[1] = 1;
    lld x = p;
    for(lld i = 2; i * i <= x; i++) {//分解p
        if(x % i) continue;
        pr[++cnt] = i;
        while(!(x % i)) x /= i;
    }
    if(x > 1) pr[++cnt] = x;
    for(int i = 2; i <= n; i++) {
        lld x = i;
        for(int j = 1; j <= cnt; j++) {
            c[i][j] = c[i - 1][j];//指数加上之前的
            while(!(x % pr[j])) x /= pr[j], c[i][j]++;
        }
        f[i] = f[i - 1] * x % p;//阶乘
        inv[i] = powe(f[i], phi - 1);//逆元
    }
}
lld comb(lld _n, lld m) {
    if(m < 0 || _n < m || n <= 0) return 0;
    if(m == 0) return 1;
    lld tmp = f[_n] * inv[m] % p * inv[_n - m] % p;
    for(int i = 1; i <= cnt; i++) {
        tmp = (tmp * powe(pr[i], c[_n][i] - c[m][i] - c[_n - m][i])) % p;//乘回来
    }
    return tmp;
}
int main() {
//  freopen("data.in", "r", stdin);
    scanf("%lld%lld%lld%lld", &n, &p, &l, &r);
    phi = p; lld d = p;//算phi函数
    for(lld i = 2; i * i <= d; i++) {
        if(d % i) continue;
        phi = phi / i * (i - 1);
        while(!(d % i)) d /= i;
    }
    if(d > 1) phi = phi / d * (d - 1);
    calc(); lld ans = 0; 
    r = min(n, r);
    for(lld i = 0; i <= n - l; i++) {
        lld tmp = (comb(n - i, (n - i - l) >> 1) - comb(n - i, (n - i - r - 1) >> 1) + p) % p;
        ans += (tmp * comb(n, i)) % p; 
        ans = ans % p;
    }
    printf("%lld", ans);
    return 0;
}

Je suppose que tu aimes

Origine www.cnblogs.com/mcggvc/p/12466581.html
conseillé
Classement