UVA-11625-Nice Prefixes (DP+矩阵快速幂)
2024-08-28 15:28:05
题面
题意:
你有K个字母,你需要用K个字母组成L长度的字符串,定义对于该字符串的任意前缀P 必须满足 ,输出方案数%1000000007的值。
思路:
首先可以想到一种简单的dp方程 dp [ len ] [ a ] [b ] 表示当前字符串长度为len 个数为最多的字母有 a个 个数次多的有b个 (那么个数最少的有k-a-b个)状态数有 100*100,没办法矩阵快速幂加速dp.
考虑对于某个固定长度 len 如果确定 a,容易发现 b = (len % K - a), 发现dp方程可以转化成 dp[ len ] [ a ] 但是依旧不能矩阵快速幂 ,因为对于len-1到len的 每个状态 a 的转移方程的系数与 len%K 相关,
于是稍微转换一下方程 由 len-K 转移到 len (每次放K个字符 ),这时候容易发现 转移方程的系数也不在改变了 于是我们先预处理放K步的dp方程的系数矩阵 然后转移L/K次 (利用矩阵快速幂加速),最后剩下L%K步暴力dp就好了
(参考了别人的题解)
代码:
#include <stdio.h>
#include <bits/stdc++.h>
#define IV inline void
typedef unsigned long long ull;
using namespace std;
const int mod = 1e9+;
ull dp[][][],B[][],A[][],C[][];
int K,t;
IV DP(int L)
{
for (int len=;len<=L;len++){
for (int i=;i<K;i++){
for (int j=;j<=K;j++){
int w=*K+len-;
int l2=w-*(j-);
while (l2+(j-)>K)l2-=K;
if (l2>=)dp[len][i][j%K]+=dp[len-][i][j-]*(l2);
if (j==&&l2>=)dp[len][i][j%K]+=dp[len-][i][l2]*(l2);
l2=w-*j;
while (l2+j>K)l2-=K;
int l3=K-j-l2;
if (l2>=&&l3>=)dp[len][i][j%K]+=dp[len-][i][j%K]*(l3);
dp[len][i][j%K]%=mod;
}
}
}
}
IV init()
{
memset(dp,,sizeof(dp));
memset(B,,sizeof(B));
B[][]=;
for (int i=;i<K;i++)dp[][i][i]=;
DP(K);
for (int i=;i<K;i++)for (int j=;j<K;j++)A[i][j]=dp[K][i][j];
}
IV mul(ull A[][],ull B[][])
{
memset(C,,sizeof(C));
for (int i=;i<K;i++)
for (int j=;j<K;j++)
for (int k=;k<K;k++)
C[i][k]=(C[i][k]+A[i][j]*B[j][k])%mod;
memcpy(A,C,sizeof(C));
}
IV pow(long long n)
{
while (n){
if (n&)mul(B,A);
mul(A,A);
n>>=;
}
}
int main()
{
long long n,ans;
scanf("%d",&t);
while (t--&&~scanf("%lld%d",&n,&K)){
ans=;
init();
pow(n/K);
memset(dp,,sizeof(dp));
for (int i=;i<K;i++)
for (int j=;j<K;j++)
dp[][i][j]=B[i][j];
DP(n%K);
int L=n%K;
for (int j=;j<K;j++)ans+=dp[L][][j];
printf("%lld\n",ans%mod);
}
return ;
}
最新文章
- 我如何介绍 Microservice
- UVALive 4431 Fruit Weights --floyd,差分约束?
- option对象概念
- Vue.2.0.5-事件处理器
- 分页写入文件,第二次分页前一定要关闭IO流啊。。否则文件写不全。。- -粗心
- VS2010 C++ 操作Excel表格的编程实现
- ssh git设置命令行
- [iOS基础控件 - 6.8] 各种数据类型的@property属性
- MLlib-协同过滤
- 射频识别技术漫谈(21)——RC系列射频芯片的天线设计
- Http学习之使用HttpURLConnection发送post和get请求(3)
- Docker(社区版) centos版 安装
- 【转】布同:如何循序渐进学习Python语言
- Spring Boot 2.x(七):优雅的处理异常
- metamask的使用
- VC.遍历文件夹中的文件
- redux笔记1
- ScheduledThreadPoolExecutor 使用线程池执行定时任务
- cxVerticalGrid赋值是实时更新
- Git学习(二)(2015年11月18日)(2016年1月29日)