嘟嘟嘟




要是求交错序列的个数和就好了,那我一秒就能切。

换成这个,我就不会了。

我一直想枚举1的个数,然后算出在长度为\(n\)的序列里,有多少个合法的序列,然后又觉得这好像是什么插板法,但是每一个盒子里必须有球,还不会。查了一下发现这东西\(O(1)\)还求不了,于是彻底放弃了。




正解是这样的,首先还得稍微推一下式子。

\[x ^ a y ^ b = (n - y) ^ a y ^ b
\]

然后利用二项式定理

\[(n - y) ^ a y ^ b = \sum _ {i = 0} ^ a C_{a} ^ {i} n ^ i (-1) ^ {a - i} y ^ {a + b - i}
\]

于是我们发现,只用求\(y\)的和的\(x\)次幂就行了。

怎么求咧,这时候就要用dp了。

令\(dp[i][j][0 / 1]\)表示长度为\(i\)的序列中,这一位填0 / 1时1的个数的\(j\)次幂。那么分情况转移:

当这一位填0时,1的个数不变,则\(dp[i][j][0] = dp[i - 1][j][0] + dp[i - 1][j][1]\)。

当这一位填1时,考虑\(y\)加了1,则\((y + 1) ^ j = \sum _ {k = 0} ^ {j} C_{j} ^ {k} y ^ j\),于是有\(dp[i][j][1] = \sum _ {k = 0} ^ {j} C_{j} ^ {k} dp[i - 1][j][0]\)

讲真这时候维护前缀和\(O(n)\)dp应该已经能过了,但是交上去就是TLE,所以只能改成矩乘了(还得卡常)。




矩阵是一个边长为\(2(a + b)\)的正方形矩阵,用样例一构造后的矩阵张这个样子:

1 0 0 0 1 0 0 0

0 1 0 0 0 1 0 0

0 0 1 0 0 0 1 0

0 0 0 1 0 0 0 1

1 0 0 0 0 0 0 0

1 1 0 0 0 0 0 0

1 2 1 0 0 0 0 0

1 3 3 1 0 0 0 0




总结一下,感觉上点难度的dp题有一部分就是在dp之前先要推一推式子,推到觉得可以dp的时候再开始dp。至于啥时候觉得可以dp,估计这就得靠刷题吧……

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 205;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
} int n, a, b, mod, Max;
struct Mat
{
ll a[maxn][maxn];
In Mat operator * (const Mat& oth)const
{
static Mat ret; Mem(ret.a, 0);
for(int i = 0; i <= Max; ++i)
for(int j = 0; j <= Max; ++j)
{
for(int k = 0; k <= Max; ++k) ret.a[i][j] += a[i][k] * oth.a[k][j];
ret.a[i][j] %= mod;
}
return ret;
}
}f;
ll C[maxn][maxn];
In void init()
{
for(int i = 0; i <= a + b; ++i) C[i][0] = 1;
for(int i = 1; i <= a + b; ++i)
for(int j = 1; j <= i; ++j) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
Mem(f.a, 0); Max = ((a + b) << 1) + 1;
for(int i = 0; i <= a + b; ++i) f.a[i][i] = f.a[i][a + b + 1 + i] = 1;
for(int i = 0; i <= a + b; ++i)
for(int j = 0; j <= i; ++j) f.a[a + b + 1 + i][j] = C[i][j];
} In Mat quickpow(Mat A, ll b)
{
Mat ret; Mem(ret.a, 0);
for(int i = 0; i <= Max; ++i) ret.a[i][i] = 1;
for(; b; b >>= 1, A = A * A)
if(b & 1) ret = ret * A;
return ret;
} ll ans[maxn];
int main()
{
n = read(), a = read(), b = read(), mod = read();
init();
Mat A = quickpow(f, n);
for(int i = 0; i <= a; ++i)
{
for(int j = 0; j <= Max; ++j) ans[i] += A.a[i][j];
for(int j = 0; j <= Max; ++j) ans[i] += A.a[a + b + 1 + i][j];
ans[i] %= mod;
}
ll Ans = 0, tp = 1;
for(int i = 0, flg = pow(-1, a); i <= a; ++i, tp = tp * n % mod, flg *= (-1))
Ans = (Ans + C[a][i] * tp % mod * (A.a[a + b - i][0] + A.a[a + b - i + a + b + 1][0]) * flg % mod + mod) % mod;
write(Ans), enter;
return 0;
}

[CQOI2018]交错序列的更多相关文章

  1. 【BZOJ5298】[CQOI2018]交错序列(动态规划,矩阵快速幂)

    [BZOJ5298][CQOI2018]交错序列(动态规划,矩阵快速幂) 题面 BZOJ 洛谷 题解 考虑由\(x\)个\(1\)和\(y\)个\(0\)组成的合法串的个数. 显然就是把\(1\)当做 ...

  2. [CQOI2018]交错序列 (矩阵快速幂,数论)

    [CQOI2018]交错序列 \(solution:\) 这一题出得真的很好,将原本一道矩阵快速幂硬生生加入组合数的标签,还那么没有违和感,那么让人看不出来.所以做这道题必须先知道(矩阵快速幂及如何构 ...

  3. BZOJ5298 CQOI2018 交错序列 【DP+矩阵快速幂优化】*

    BZOJ5298 CQOI2018 交错序列 [DP+矩阵快速幂优化] Description 我们称一个仅由0.1构成的序列为"交错序列",当且仅当序列中没有相邻的1(可以有相邻 ...

  4. bzoj 5298: [Cqoi2018]交错序列

    Description 我们称一个仅由0.1构成的序列为"交错序列",当且仅当序列中没有相邻的1(可以有相邻的0).例如,000,001 ,101,都是交错序列,而110则不是.对 ...

  5. BZOJ5298 [CQOI2018] 交错序列 | 矩阵乘法和一个trick

    题面 求所有长度为\(n\)的.没有相邻的1的01序列中,若0有\(x\)个.1有\(y\)个,\(x^ay^b\)之和(对\(m\)取模). \(n \le 10^7, m \le 10^8, 0 ...

  6. BZOJ5298 CQOI2018交错序列(动态规划+矩阵快速幂)

    显然答案为Σkb·(n-k)a·C(n-k+1,k).并且可以发现ΣC(n-k,k)=fibn.但这实际上没有任何卵用. 纯组合看起来不太行得通,换个思路,考虑一个显然的dp,即设f[i][j][0/ ...

  7. [BZOJ5298][CQOI2018]交错序列(DP+矩阵乘法)

    https://blog.csdn.net/dream_maker_yk/article/details/80377490 斯特林数有时并没有用. #include<cstdio> #in ...

  8. 【[CQOI2018]交错序列】

    这个题简直有毒,\(O((a+b)^3logn)\)的做法不卡常只比\(O(2^n*n)\)多\(10\)分 看到\(a\)和\(b\)简直小的可怜,于是可以往矩阵上联想 发现这个柿子有些特殊,好像可 ...

  9. cqoi2018

    题解: 很多模板题 第一次写莫队还比较顺利 除了把排序的cmp写错..(还第一次遇到) 这题分块也可以 先预处理出g[i][j]代表前i个块,颜色为j的有多少种 f[i][j]表示i-j的块能构成多少 ...

随机推荐

  1. windows 上用 docker 部署aspnetcore 2.0

       首先下载docker for windows 并且 安装. 这其中需要显卡支持虚拟化  windows系统升级到专业版  bois 启用虚拟   通过vs2017 创建一个net core ap ...

  2. 借鉴Glide思想二次封装Fresco

    本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 最近封装了个 Fresco 的组件库:DFresco,就顺便来讲讲. 背景 Fresco 图片库很强大,我们项目中就是使用的 Fre ...

  3. 二进制安装 kubernetes 1.12(五) - 运行测试实例

    检查集群状态 # 在 master 上 kubectl get node kubectl get cs 注册登录阿里云容器仓库 因国内无法获得 google 的 pause-amd64 镜像,我这里使 ...

  4. 洛谷P4723 【模板】线性递推(多项式取模 线性代数)

    题意 题目链接 Sol Orz shadowice 注意,下面的代码自带O(随时TLE)倍大常数.. #include<bits/stdc++.h> #define Pair pair&l ...

  5. java程序存入数据库中文乱码解决方案

    一.问题描述 背景:代码迁移,ssm框架在插入数据到mysql数据库时,中文乱码.代码中的编码配置没有问题,因为该项目代码以前使用过,没有问题.现在换了数据库,数据库配置也做了修改,统一使用utf8, ...

  6. 关于Object数组强转成Integer数组的问题:Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;

    一.当把Object数组,强转的具体的Integer数组时,会报错. 代码如下: //数组强转报错演示 Object[] numbers = {1,2,3}; Integer[] ints = (In ...

  7. Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AOP编程比较

    本篇博文用一个稍复杂点的案例来对比一下基于XML配置与基于AspectJ注解配置的AOP编程的不同. 相关引入包等Spring  AOP编程准备,请参考小编的其他博文,这里不再赘述. 案例要求: 写一 ...

  8. Python变量和简单数据类型

    变量的命名和使用 在Python中使用变量时 ,需要遵守一定的规则和指南. 变量名只能包含字母‘数字和下划线 变量名不能包含空格,但可以用下划线分割其中单词 不要将Python关键字和函数名用作变量名 ...

  9. 小程序实践(六):view内部组件排版

    涉及知识点: 1.垂直排列,水平排列 2.居中对齐 示例: 1.默认排版 , 一个父组件里面两个子view 显示效果: 2.先给父view设置一个高度和颜色值,用于看效果 3.实现水平排列和垂直排列的 ...

  10. Android为TV端助力 转载:android MVC设计模式

    Controller控制器 import android.app.Dialog; import android.app.ProgressDialog; import android.os.Bundle ...