设为首页 加入收藏

TOP

hdu 3658(矩阵快速幂)
2015-11-21 01:00:33 来源: 作者: 【 】 浏览:1
Tags:hdu 3658 矩阵 快速

题意:一个长度为m的字符串需要填充,填充字母必须是’A’ ~ ‘Z’,’a’ ~ ‘z’,要求字符串相邻字符的ascii值的差值≤32,且必须至少存在一个相邻字符差值等于32。问有多少种填充方式。
题解:直接构造至少存在一个相邻字符差值等于32的不好做,可以逆着想,先求出差值>=32的所有情况,再求出差值<32的所有情况,两个结果相减就是解。

#include 
   
     #include 
    
      #include 
     
       using namespace std; const int MOD = 1000000007; struct Mat { long long g[55][55]; }ori, res, ori2, res2; long long m; Mat multiply(Mat x, Mat y) { Mat temp; for (int i = 0; i < 52; i++) for (int j = 0; j < 52; j++) { temp.g[i][j] = 0; for (int k = 0; k < 52; k++) temp.g[i][j] = (temp.g[i][j] + x.g[i][k] * y.g[k][j]) % MOD; } return temp; } void calc1(long long m) { while (m) { if (m & 1) ori2 = multiply(ori2, res2); m >>= 1; res2 = multiply(res2, res2); } } void calc2(long long m) { while (m) { if (m & 1) ori = multiply(ori, res); m >>= 1; res = multiply(res, res); } } int main() { int t; scanf("%d", &t); while (t--) { scanf("%lld", &m); memset(res.g, 0, sizeof(res.g)); memset(ori.g, 0, sizeof(ori.g)); memset(res2.g, 0, sizeof(res2.g)); memset(ori2.g, 0, sizeof(ori2.g)); for (int i = 0; i < 26; i++) { for (int j = 0; j <= i + 26; j++) res.g[j][i] = res2.g[j][i] = 1; res2.g[i + 26][i] = 0; } for (int i = 26; i < 52; i++) { for (int j = 51; j >= i - 26; j--) res.g[j][i] = res2.g[j][i] = 1; res2.g[i - 26][i] = 0; } for (int i = 0; i < 52; i++) ori.g[0][i] = ori2.g[0][i] = 1; calc1(m - 1); calc2(m - 1); long long ans1 = 0, ans2 = 0; for (int i = 0; i < 52; i++) { ans1 = (ans1 + ori.g[0][i]) % MOD; ans2 = (ans2 + ori2.g[0][i]) % MOD; } printf("%lld\n", (ans1 + MOD - ans2) % MOD); } return 0; }
     
    
   
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇ACdream1139 Sum(推公式+逆元求解) 下一篇uva 12470(矩阵快速幂)

评论

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