题目(vjudge)

题面

题意:

  你有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 ;
}

最新文章

  1. 我如何介绍 Microservice
  2. UVALive 4431 Fruit Weights --floyd,差分约束?
  3. option对象概念
  4. Vue.2.0.5-事件处理器
  5. 分页写入文件,第二次分页前一定要关闭IO流啊。。否则文件写不全。。- -粗心
  6. VS2010 C++ 操作Excel表格的编程实现
  7. ssh git设置命令行
  8. [iOS基础控件 - 6.8] 各种数据类型的@property属性
  9. MLlib-协同过滤
  10. 射频识别技术漫谈(21)——RC系列射频芯片的天线设计
  11. Http学习之使用HttpURLConnection发送post和get请求(3)
  12. Docker(社区版) centos版 安装
  13. 【转】布同:如何循序渐进学习Python语言
  14. Spring Boot 2.x(七):优雅的处理异常
  15. metamask的使用
  16. VC.遍历文件夹中的文件
  17. redux笔记1
  18. ScheduledThreadPoolExecutor 使用线程池执行定时任务
  19. cxVerticalGrid赋值是实时更新
  20. Git学习(二)(2015年11月18日)(2016年1月29日)

热门文章

  1. Xamarin XAML语言教程基本页面ContentPage占用面积
  2. kotlin扩展函数
  3. 【bzoj1485:】【 [HNOI2009]有趣的数列】模任意数的卡特兰数
  4. ORACLE查询当前连接的用户信息及操作的SQL语句
  5. 第七章 android-UI组件
  6. 字母数字、字母、汉字验证码 (java)
  7. VBA 时间相关的函数
  8. kubernetes1.5.2集群部署过程--安全模式
  9. Android Server Push - MQTT推送实现tokudu
  10. 新人补钙系列教程之:AS 与 JS 相互通信