https://ac.nowcoder.com/acm/contest/317/H

C++版本一

std

题解:

 

#include<cstdio>
#include<cstring>
#define int long long 
#define LL int
const int MAXN = 2e6 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, mod, prime[MAXN], vis[MAXN], tot, mn[MAXN], num[MAXN], K;
void GetPhi(int N) {
    vis[1] = 1;
    for(int i = 2; i <= N; i++) {
        if(!vis[i]) prime[++tot] = i, mn[i] = tot;
        for(int j = 1; j <= tot && (i * prime[j] <= N); j++) {
            vis[i * prime[j]] = 1; mn[i * prime[j]] = j;
            if(!(i % prime[j])) break;
        }
    }
}
void insert(int x, int opt) {
    while(x != 1) num[mn[x]] += opt, x = x / prime[mn[x]];
}
int fastpow(int a, int p) {
    int base = 1;
    while(p) {
        if(p & 1) base = (1ll * base * a) % mod;
        a = (1ll * a * a) % mod; p >>= 1;
    }
    return base;
}
int FindAns() {
    LL ans = 1;
    for(int i = 1; i <= tot; i++) 
        if(num[i]) 
            ans = (1ll * ans * fastpow(prime[i], num[i])) % mod;	
    return ans;
}
signed main() {
    N = read();  K = read(); mod = read();
    GetPhi(2 * N);
    for(int i = N + 1; i <= 2 * N; i++) insert(i, 1);
    for(int i = 1; i <= N; i++) insert(i, -1);
    LL ans1 = FindAns();
    memset(num, 0, sizeof(num));
    
    for(int i = N + K + 1; i <= 2 * N; i++) insert(i, 1);
    for(int i = 1; i <= N - K; i++) insert(i, -1);

    LL ans2 = FindAns();
    printf("%lld", (ans1 - ans2 + mod) % mod);

    return 0;
}