设为首页 加入收藏

TOP

hdu3658(矩阵快速幂)
2015-11-21 01:00:36 来源: 作者: 【 】 浏览:2
Tags:hdu3658 矩阵 快速

题意:

给出一个序列的长度;

这个序列只能有A-Z,a-z;

而且要求相邻的字母asiic 码差值小于等于32;而且必须有一个是等于32的;

问有种排列;

?

思路:

构造一个52  * 52的矩阵,把每个字母后面能跟哪些标为1;

然后矩阵快速幂;

然后再把差值为32的标志为0,在算一次(这样算出来的就是肯定不会有差值等于32的)

两次结果相减;

?

?

#include
  
   
#include
   
     #define ll long long struct mat { ll g[60][60]; }res, ori; const ll MOD = 1e9 + 7; ll n; void init() { memset(ori.g ,0, sizeof(ori.g)); memset(res.g ,0, sizeof(res.g)); for(int i = 0; i < 26; i++) { for(int j = 0; j <= i + 26; j++) { ori.g[j][i] = 1; } } for(int i = 26; i < 52; i++) { for(int j = 51; j >= i - 26 ; j--) { ori.g[j][i] = 1; } } for(int i = 0; i < 52; i++) { res.g[0][i] = 1; } } mat mul(mat a, mat b) { mat tmp; memset(tmp.g, 0, sizeof(tmp.g)); for(int i = 0; i < 52; i++) { for(int j = 0; j < 52; j++) { for(int k = 0; k < 52; k++) { tmp.g[i][j] = (tmp.g[i][j] + a.g[i][k] * b.g[k][j])% MOD; } } } return tmp; } ll cul(ll k) { while(k) { if(k & 1) res = mul(res, ori); k >>= 1; ori = mul(ori, ori); } ll ans = 0; for(int i = 0; i < 52; i++) { ans = (ans + res.g[0][i]) % MOD; } return ans; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%lld",&n); init(); ll k1 = cul(n - 1); init(); for(int i = 0; i < 26; i++) { ori.g[i + 26][i] = 0; } for(int i = 26; i < 52; i++) { ori.g[i - 26][i] = 0; } ll k2 = cul(n - 1); printf("%lld\n",(k1 + MOD- k2) % MOD); } }
   
  


?

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++ 常用代码001 IsValidFileName.. 下一篇基于UDP的Winsock编程(C++版)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: