CSA49G
XSY3315
因为判断两串是否本质不同只看某几项是不是好数,与究竟是哪个好数无关,所以考虑转换一下题意:
给出一个长度为aka_kak​的01串SSS,第a1,a2,...,aka_1,a_2,...,a_ka1​,a2​,...,ak​项为1,其余项为0。
现要用若干个SSS的前缀拼出串TTT,使得TTT中有nnn个1,以1结尾,并且任意两个1之间0的个数不超过mmm。问所有不同的TTT的长度之和为多少?

SSS如果用01串表示,会很长,发现kkk很小,考虑换一种表示方式:设bi=ai−ai−1b_i=a_i-a_{i-1}bi​=ai​−ai−1​。我们把SSS串描述成{b1,b2,b3,...,bk}\{b_1,b_2,b_3,...,b_k\}{b1​,b2​,b3​,...,bk​},表示SSS由 (b1−1)(b_1-1)(b1​−1)个0,1个1,(b2−1)(b_2-1)(b2​−1)个0,1个1,…,(bk−1)(b_k-1)(bk​−1)个0,1个1 拼接而成。

设g(x,i)g(x,i)g(x,i)表示目前有xxx个1,以 (bi−1)(b_i-1)(bi​−1)个0+1个1 结尾的01串个数,
f(x,i)f(x,i)f(x,i)表示目前有xxx个1,以 (bi−1)(b_i-1)(bi​−1)个0+1个1 结尾的01串长度之和。
可以列出dp式:

g(x,i)={g(x−1,i−1)i>1∑j=1kg(x−1,j)×(m−a[1]+1)i=1g(x,i)=\begin{cases}g(x-1,i-1)\qquad i>1\\\sum_{j=1}^{k}g(x-1,j)\times(m-a[1]+1)\qquad i=1\end{cases}g(x,i)={g(x−1,i−1)i>1∑j=1k​g(x−1,j)×(m−a[1]+1)i=1​

f(x,i)={f(x−1,i−1)+(a[i]−a[i−1])×g(x−1,i−1)i>1∑j=1kf(x−1,j)×(m−a[1]+1)+g(x−1,j)×(a[1]+m)(m−a[1]+1)2i=1f(x,i)=\begin{cases}f(x-1,i-1)+(a[i]-a[i-1])\times g(x-1,i-1)\qquad i>1\\\sum_{j=1}^{k}f(x-1,j)\times(m-a[1]+1)+g(x-1,j)\times\frac{(a[1]+m)(m-a[1]+1)}{2}\qquad i=1\end{cases}f(x,i)={f(x−1,i−1)+(a[i]−a[i−1])×g(x−1,i−1)i>1∑j=1k​f(x−1,j)×(m−a[1]+1)+g(x−1,j)×2(a[1]+m)(m−a[1]+1)​i=1​

把式子用矩阵快速幂优化一下,复杂度是O(k3logn)O(k^3logn)O(k3logn)
(ps.因为fff的转移同时与f,gf,gf,g有关,所以通过矩乘转移的过程有点特殊,具体可以看代码。)

然而还有一个小小的问题:
假设a={2,6,7,9,13}a=\{2,6,7,9,13\}a={2,6,7,9,13},
那么S[1−13]=0100011010001S[1-13]=0100011010001S[1−13]=0100011010001,S[1−6]=010001S[1-6]=010001S[1−6]=010001,S[1−7]=0100011S[1-7]=0100011S[1−7]=0100011。
我们发现S[1−7]+S[1−6]=S[1−13]S[1-7]+S[1-6]=S[1-13]S[1−7]+S[1−6]=S[1−13],即若S[1−y]S[1-y]S[1−y]是S[1−x]S[1-x]S[1−x]的后缀,则S[1−x]S[1-x]S[1−x]可以由S[1−y]S[1-y]S[1−y],S[1−(x−y)]S[1-(x-y)]S[1−(x−y)]拼成。但仔细看上面的dp式就会发现S[1−7]+S[1−6]S[1-7]+S[1-6]S[1−7]+S[1−6]和S[1−13]S[1-13]S[1−13]被算成了两个串。怎么办?暴力预处理一下,对于前缀S[1−x]S[1-x]S[1−x],若有前缀S[1−y]S[1-y]S[1−y]同时是S[1−x]S[1-x]S[1−x]的后缀,则前缀S[1−x]S[1-x]S[1−x]不能取。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int K=110;
int kk,m,n,a[K],pd[K][K],flag[K],ans;
struct Matrix{int n,m,g[K][K],f[K][K];//g:个数 f:长度和 Matrix(int x=0,int y=0){memset(f,0,sizeof(f));memset(g,0,sizeof(g));n=x,m=y;}friend Matrix operator * (Matrix a,Matrix b){Matrix res(a.n,b.m);for(int i=1;i<=a.n;i++){for(int j=1;j<=b.m;j++){__int128 g=0,f=0;for(int k=1;k<=a.m;k++){g+=1ll*a.g[i][k]*b.g[k][j];f+=1ll*a.f[i][k]*b.g[k][j]+1ll*a.g[i][k]*b.f[k][j];}res.g[i][j]=int(g%mod);res.f[i][j]=int(f%mod);}}return res;}
};
int Sum(ll x,ll y){return (x+y)*(y-x+1)/2%mod;
}
int main(){scanf("%d%d%d",&kk,&m,&n);for(int i=1;i<=kk;i++) scanf("%d",&a[i]);sort(a+1,a+kk+1);pd[1][1]=1;for(int i=2;i<=kk;i++){int fl=0;for(int j=2;j<=i;j++){if(pd[i-1][j-1]==1) fl=1;if(pd[i-1][j-1]==1&&(a[j]-a[j-1])==(a[i]-a[i-1])) pd[i][j]=1;}if(a[1]<=a[i]-a[i-1]&&fl) pd[i][1]=1;for(int j=1;j<i;j++)if(pd[i][j]==1) flag[i]=1;}Matrix A(kk,kk),res(1,kk);for(int i=1;i<=kk;i++){if(flag[i]==0){A.g[i][1]=max(m-a[1]+1,0);A.f[i][1]=max(Sum(a[1],m),0);}       }for(int i=1;i<kk;i++){if(a[i+1]-a[i]<=m){A.g[i][i+1]=1;A.f[i][i+1]=a[i+1]-a[i];}}res.g[1][1]=max(m-a[1]+1,0);res.f[1][1]=max(Sum(a[1],m),0);int b=n-1;while(b){if(b&1) res=res*A;b>>=1;A=A*A;}for(int i=1;i<=kk;i++){if(flag[i]==0) ans=(ans+res.f[1][i])%mod;}printf("%d\n",ans);return 0;
}

[CSA49G][XSY3315] Bunny on Number Line (DP)相关推荐

  1. HDU4055 - number string(DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4055 思路:dp[i][j]表示处理前i个字符以j结尾可能的序列数. 当a[i]=='I'时,dp[i ...

  2. 「CSA49」Bunny on Number Line

    「CSA49」Bunny on Number Line 题目大意:有一个人从0开始走,每次可以向前走一步或者回到1,那么会产生一个位置序列,其中给出 \(k\) 个位置是好的.定义一个位置序列是好的, ...

  3. 【CF 149D】Coloring Brackets(dp)

    [CF 149D]Coloring Brackets(dp) D. Coloring Brackets time limit per test 2 seconds memory limit per t ...

  4. 求三角形最大面积(DP)

    求三角形最大面积(DP) 在OJ上奇迹般WA了:WA:70. Why? #include <iostream> #include <string.h> using namesp ...

  5. LeetCode 编辑距离 II(DP)

    1. 题目 给你两个单词 s 和 t,请你计算出将 s 转换成 t 所使用的最少操作数. 你可以对一个单词进行如下两种操作: 删除一个字符 替换一个字符 注意: 不允许插入操作 题目保证有解 示例: ...

  6. LeetCode 1220. 统计元音字母序列的数目(DP)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个整数 n,请你帮忙统计一下我们可以按下述规则形成多少个长度为 n 的字符串: - 字符串中的每个字符都应当是小写元音字母('a', 'e', 'i ...

  7. LeetCode 265. 粉刷房子 II(DP)

    文章目录 1. 题目 2. 解题 1. 题目 假如有一排房子,共 n 个,每个房子可以被粉刷成 k 种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同. 当然,因为市场上不同颜色油 ...

  8. LeetCode 256. 粉刷房子(DP)

    文章目录 1. 题目 2. 解题 1. 题目 假如有一排房子,共 n 个,每个房子可以被粉刷成红色.蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其与相邻的两个房子颜色不能相同. 当然,因 ...

  9. LeetCode 1223. 掷骰子模拟(DP)

    1. 题目 有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始 ...

最新文章

  1. EMNLP2020:Hugging Face获最佳demo
  2. Maven常用插件--转
  3. Linux下KVM虚拟机基本管理及常用命令(转)
  4. C++继承同名静态成员处理
  5. JupyterHub on Kubernetes-Helm安装
  6. ASP.NET会话(Session)模式
  7. Aibaba Dubbo 的前世今生以及黑历史 主程序员梁飞 阿里P9(2016年查看)
  8. 实时数据库与时序数据库
  9. 创建学生管理系统java实训1
  10. ADS仿真学习:s2p文件导入ADS
  11. php日历天气预报下载安装手机桌面_手机桌面时钟日历天气
  12. 【大杂烩】杂7杂8的东西
  13. R SMOTE 报错 length of 'dimnames' [2] not equal to array extent
  14. stl文件用proe怎么打开_3dmax怎么导入stl文件?如何将proe的文件导入3dmax进行渲染?...
  15. 高中数学立体几何知识汇总(暑假复习资料)
  16. 实现阿里云SSH免密登录
  17. Ethercat-IghMaster 1.5.2调试笔记
  18. linux玩大型游戏下载软件,5个最受欢迎Linux版大型FPS游戏
  19. R语言实现常用多重比较方法
  20. C语言计算礼炮声响次数(穷举和递推)

热门文章

  1. java io操作_Java 的IO操作(文件的读,写操作)
  2. excel怎么在柱状图上加超链_如何让你的年终总结更符合领导心意,高薪员工必备的excel技能...
  3. 数据库课设(足球联赛管理系统)
  4. [PAT乙级]1036 跟奥巴马一起编程
  5. [Qt入门]QTableWidget控件创建
  6. Good Number Gym - 102769G 2020年CCPC秦皇岛分站赛
  7. Rochambeau POJ - 2912 (枚举和加权并查集+路径压缩)找唯一裁判
  8. 计算机公共基础知识实验报告,20140902413 李雪瑞 计算机工程系实验报告345.docx...
  9. chrome主题_谷歌Chrome将很快允许用户创建自定义主题
  10. DataFrame的多dtype创建方法