CF896D

CF896D

说一下感觉有用的点:

1.对卡特兰数敏感一些,就是一些加减的操作,要保证每时每刻都为正。

2.对于组合数取模,模数非质数。

设模数为 mod ,将模数分解质因数,即:mod=P1m1P2m2Pcntmcntcnt 即模数的质因数个数。

对于组合数中阶乘的取模,预处理, 1n 枚举要乘的数,记为 res

res 分解成 res=P1c1P2c2Pcntccntx 的形式,这里的 P 是模数的质因子,可以发现 xmod 互质,根据欧拉定理:当 gcd(a,b)=1aphib1 (mod b) ,用快速幂可以求出 x 关于 mod 的逆元。

之后做一下分解数 的质因子的前缀和,因为只涉及到乘和除的操作,相当于是将这个数乘这些质因子再乘回去。

Code moo~~
using namespace std;
#define int long long
#define re register int
#define pc_ putchar(' ')
#define pc_n putchar('\n')
#define Bessie signed
const int CTR = 2e5 + 7;
int n, MOD, l, r;
int phi;
int qpow(int x, int y) {
int base = 1;
while(y) {
if(y & 1) base = base * x % MOD;
x = x * x % MOD;
y >>= 1;
}
return base;
}
int p[CTR], cnt;
int zs[CTR][40];
int jc[CTR], inv[CTR];
void init() {
int res = MOD;
for(re i = 2; i * i <= res; ++i) {
if(res % i) continue;
p[++cnt] = i;
while(!(res % i)) res /= i;
}
if(res != 1) p[++cnt] = res;
jc[0] = inv[0] = jc[1] = inv[1] = 1;
for(re i = 2, res; i <= n; ++i) {
res = i;
for(re j = 1; j <= cnt; ++j) {
zs[i][j] = zs[i - 1][j];
while(!(res % p[j])) {
res /= p[j];
++zs[i][j];
}
}
jc[i] = jc[i - 1] * res % MOD;
inv[i] = qpow(jc[i], phi - 1);
}
}
int C(int n, int m) {
if(n < m) return 0;
if(m == 0) return 1;
int res = jc[n] * inv[m] % MOD * inv[n - m] % MOD;
for(re i = 1; i <= cnt; ++i) (res *= qpow(p[i], zs[n][i] - zs[n - m][i] - zs[m][i])) %= MOD;
return res;
}
int ans;
Bessie main() {
n = read(), MOD = read(), l = read(), r = read();
int res = MOD;
phi = MOD;
for(re i = 2; i * i <= MOD; ++i) {
if(res % i) continue;
phi = phi / i * (i - 1);
while(!(res % i)) res /= i;
}
if(res != 1) phi = phi / res * (res - 1);
init();
for(re i = 0; i <= n; ++i) (ans += C(n, i) * ((C(i, ceil((double)(i + l) / 2))) - C(i, (i + r) / 2 + 1) % MOD + MOD) % MOD) %= MOD;
ot(ans);
return 0;
}

hzoiCreator_157

posted @   Creator_157  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示