【题解】P4456 [CQOI2018] 交错序列(数学递推)

P4456 CQOI2018 交错序列 - 洛谷 (luogu.com.cn)

时间复杂度线性。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

const int N = 1e7 + 10;  
int fac[N], inv[N], P;

int qpow(int a, int b) {
    int c = 1;
    while (b) {
        if (b & 1) c = 1ll * c * a % P;
        a = 1ll * a * a % P;
        b >>= 1;
    }
    return c;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
	
	int n, a, b;
    cin >> n >> a >> b >> P;

    fac[0] = 1;
    for (int i = 1; i <= n + 1; i ++) {
        fac[i] = 1ll * fac[i - 1] * i % P;
    }

	inv[n + 1] = qpow(fac[n + 1], P - 2);   // (n+1)! 的逆元
	for (int i = n; i >= 0; i --)
    	inv[i] = 1ll * inv[i + 1] * (i + 1) % P;

    int ans = 0;
    // 枚举 1 的个数 i(即 y = i)
    for (int i = 0; i <= n; i ++) {
        // 交错序列中 1 不相邻,恰好有 i 个 1 的方案数为 C(n - i + 1, i)
        // 需要满足 i <= n - i + 1,即 2i <= n + 1,否则组合数为 0
        if (i <= n - i + 1) {
            // 组合数 C(n-i+1, i) = fac[n-i+1] * inv[i] * inv[n-2i+1] mod m
            // 这里 n-(i-1) = n-i+1,n-(i-1)-i = n-2i+1
            int comb = 1ll * fac[n - i + 1] * inv[i] % P * inv[n - i + 1 - i] % P;
            // 特征值:x = n - i(0 的个数),y = i(1 的个数)
            // 贡献 = 方案数 * (n-i)^a * i^b
            int term = 1ll * comb * qpow(n - i, a) % P * qpow(i, b) % P;
            ans = (ans + term) % P;
        }
    }

    cout << ans << "\n";
    return 0;
}
相关推荐
科技苑15 小时前
C++ CAS与ABA问题详解,无锁编程的经典陷阱怎么解决?
c++·人工智能
GoAI16 小时前
DeepSeek Harness Memory (一)主流记忆插件总结
后端·算法·面试
Pniubi16 小时前
力扣54.螺旋矩阵
算法·leetcode·矩阵
choumou_M19 小时前
算法_1:由浅入深学习快速排序QuickSort
学习·算法·排序算法
Coder_Shenshen19 小时前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
BaiPeter20 小时前
ZPL文件预览
开发语言·c++
心仪久了会沦陷21 小时前
C语言数据结构入门——树与二叉树详解:概念、堆实现与链式遍历
c语言·数据结构·算法
小此方21 小时前
[算法实战论:动态规划]背包问题概念,01不满背包问题,01满背包问题,背包问题的滚动数组空间优化
算法·动态规划
悠仁さん1 天前
【C++】哈希表
c++·算法·散列表