题目大意

  你有\(s_1\)种\(1\times 2\)的地砖,\(s_2\)种\(2\times 1\)的地砖。

  记铺满\(m\times n\)的地板的方案数为\(f(m,n)\)。

  给你\(m,l,r,s_1,s_2\),求\(\sum_{i=l}^rf(m,i)\)

  \(m\leq 6,1\leq l\leq r\leq {10}^{2501}\)

题解

  显然是状压DP。

  显然可以矩阵快速幂。

  怎么矩阵快速幂?

  假设矩阵是\(2^m\times 2^m\)的,我们把矩阵扩大一行一列,记录前面算出的铺满\(m\)行\(i\)列的方案数。

  转移在原来转移的基础上增加\(f_{i-1,2^m-1}\longrightarrow f_{i,2^m}\)和\(f_{i-1,2^m}\longrightarrow f_{i,2^m}\)

  这样\(f_{i,m}\)就是\(\sum_{j=1}^{i-1}f_{j,2^m-1}\)。

  然后就可以矩阵快速幂了。

  显然这个矩阵快速幂是可以用特征多项式+倍增取模优化的。

  求特征多项式可以用\(O(n^3)\)的方法,也可以用\(O(n^4)\)的方法。

  然后就没了。

  时间复杂度:\(O(8^m+4^m\log r)\)

  求矩阵的特征多项式

  Cayley-Hamilton定理&倍增取模

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<utility>
  5. #include<iostream>
  6. #include<vector>
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int,int> pii;
  10. void open(const char *s)
  11. {
  12. #ifndef ONLINE_JUDGE
  13. char str[100];
  14. sprintf(str,"%s.in",s);
  15. freopen(str,"r",stdin);
  16. sprintf(str,"%s.out",s);
  17. freopen(str,"w",stdout);
  18. #endif
  19. }
  20. typedef vector<ll> poly;
  21. const ll p=998244353;
  22. ll fp(ll a,ll b)
  23. {
  24. ll s=1;
  25. for(;b;b>>=1,a=a*a%p)
  26. if(b&1)
  27. s=s*a%p;
  28. return s;
  29. }
  30. struct matrix
  31. {
  32. ll a[130][130];
  33. int n,m;
  34. matrix()
  35. {
  36. memset(a,0,sizeof a);
  37. n=m=0;
  38. }
  39. ll *operator [](int x)
  40. {
  41. return a[x];
  42. }
  43. };
  44. matrix operator *(matrix a,matrix b)
  45. {
  46. matrix c;
  47. c.n=a.n;
  48. c.m=b.m;
  49. for(int i=0;i<a.n;i++)
  50. for(int j=0;j<a.m;j++)
  51. {
  52. ll s=0;
  53. for(int k=0;k<b.m;k++)
  54. s=(s+a[i][k]*b[k][j])%p;
  55. c[i][j]=s;
  56. }
  57. return c;
  58. }
  59. namespace yww
  60. {
  61. poly f[200];
  62. void add(poly &a,poly b,ll s1,ll s2)
  63. {
  64. int n=b.size();
  65. while(int(a.size())<n+1)
  66. a.push_back(0);
  67. for(int i=0;i<n;i++)
  68. {
  69. a[i]=(a[i]+b[i]*s2)%p;
  70. a[i+1]=(a[i+1]+b[i]*s1)%p;
  71. }
  72. while(a.back()==0)
  73. a.pop_back();
  74. }
  75. poly getpoly(matrix a,int n)
  76. {
  77. for(int i=0;i<=n;i++)
  78. {
  79. int j;
  80. for(j=i+1;j<=n;j++)
  81. if(a[j][i])
  82. break;
  83. if(j>n)
  84. continue;
  85. if(j!=i+1)
  86. {
  87. for(int k=i;k<=n;k++)
  88. swap(a[i+1][k],a[j][k]);
  89. for(int k=0;k<=n;k++)
  90. swap(a[k][i+1],a[k][j]);
  91. }
  92. for(int j=i+2;j<=n;j++)
  93. if(a[j][i])
  94. {
  95. ll v=fp(a[i+1][i],p-2)*a[j][i]%p;
  96. for(int k=i;k<=n;k++)
  97. a[j][k]=(a[j][k]-a[i+1][k]*v)%p;
  98. for(int k=0;k<=n;k++)
  99. a[k][i+1]=(a[k][i+1]+a[k][j]*v)%p;
  100. }
  101. }
  102. f[n+1].push_back(1);
  103. for(int i=n;i>=0;i--)
  104. {
  105. add(f[i],f[i+1],1,-a[i][i]);
  106. ll v=1;
  107. for(int j=i+2;j<=n+1;j++)
  108. {
  109. v=v*a[j-1][j-2]%p;
  110. add(f[i],f[j],0,-v*a[i][j-1]%p);
  111. }
  112. }
  113. return f[0];
  114. }
  115. }
  116. matrix a;
  117. int m,s1,s2,all;
  118. void dfs(int x,int a1,int a2,ll s)
  119. {
  120. if(x>m+1)
  121. return;
  122. if(x>m)
  123. {
  124. a[all^a1][a2]=(a[all^a1][a2]+s)%p;
  125. return;
  126. }
  127. dfs(x+1,a1,a2,s);
  128. dfs(x+1,a1|(1<<(x-1)),a2|(1<<(x-1)),s*s1%p);
  129. dfs(x+2,a1,a2|(3<<(x-1)),s*s2%p);
  130. }
  131. poly aa;
  132. int len;
  133. //poly f[20];
  134. matrix g[200];
  135. poly operator *(poly a,poly b)
  136. {
  137. int n=a.size()-1;
  138. int m=b.size()-1;
  139. poly c(n+m+1);
  140. for(int j=0;j<=m;j++)
  141. if(b[j])
  142. for(int i=0;i<=n;i++)
  143. c[i+j]=(c[i+j]+a[i]*b[j])%p;
  144. return c;
  145. }
  146. poly operator %(poly a,poly b)
  147. {
  148. int n=a.size()-1;
  149. int m=b.size()-1;
  150. for(int i=n;i>=m;i--)
  151. if(a[i])
  152. {
  153. ll v=a[i];
  154. for(int j=0;j<=m;j++)
  155. a[i-m+j]=(a[i-m+j]-b[j]*v)%p;
  156. }
  157. while(!a.back())
  158. a.pop_back();
  159. return a;
  160. }
  161. poly a1;
  162. void init()
  163. {
  164. all=(1<<m)-1;
  165. dfs(1,0,0,1);
  166. a[all][all+1]=1;
  167. a[all+1][all+1]=1;
  168. a.n=a.m=all+2;
  169. aa=yww::getpoly(a,all+1);
  170. len=aa.size()-1;
  171. // for(int i=0;i<=len;i++)
  172. // c[i]=aa[i];
  173. // f[0].push_back(1);
  174. // for(int i=1;i<=9;i++)
  175. // {
  176. // f[i].resize(i+1);
  177. // f[i][i]=1;
  178. // f[i]=f[i]%aa;
  179. //// for(auto v:f[i])
  180. //// printf("%lld ",(v+p)%p);
  181. //// printf("\n");
  182. // }
  183. g[0][0][all]=1;
  184. g[0].n=1;
  185. g[0].m=a.n;
  186. for(int i=1;i<len;i++)
  187. {
  188. g[i]=g[i-1]*a;
  189. // printf("%lld\n",(g[i][0][all+1]+p)%p);
  190. }
  191. a1.resize(2);
  192. a1[0]=0;
  193. a1[1]=1;
  194. a1=a1%aa;
  195. }
  196. char l[10010],r[10010];
  197. int e[100010];
  198. int bit[100010];
  199. poly f;
  200. void calc(int n)
  201. {
  202. if(!n)
  203. return;
  204. calc(n-1);
  205. f=f*f%aa;
  206. if(bit[n])
  207. f=f*a1%aa;
  208. }
  209. int solve(char *str,int b)
  210. {
  211. int n=strlen(str+1);
  212. memset(e,0,sizeof e);
  213. for(int i=1;i<=n;i++)
  214. e[i]=str[n-i+1]-'0';
  215. e[1]+=b;
  216. int i;
  217. for(i=1;e[i]>=10;i++)
  218. {
  219. e[i+1]+=e[i]/10;
  220. e[i]%=10;
  221. }
  222. n=max(n,i);
  223. memset(bit,0,sizeof bit);
  224. int k=1;
  225. for(int i=n;i>=1;i--)
  226. {
  227. int s=0;
  228. int j;
  229. for(j=1;j<=k||s;j++)
  230. {
  231. s+=bit[j]*10;
  232. bit[j]=s&1;
  233. s>>=1;
  234. }
  235. k=max(k,j);
  236. bit[1]+=e[i];
  237. for(j=1;bit[j]>=2;j++)
  238. {
  239. bit[j+1]+=bit[j]>>1;
  240. bit[j]&=1;
  241. }
  242. k=max(k,j);
  243. }
  244. f.clear();
  245. f.push_back(1);
  246. reverse(bit+1,bit+k+1);
  247. calc(k);
  248. ll ans=0;
  249. for(int i=0;i<f.size()&&i<len;i++)
  250. {
  251. // printf("%lld\n",(f[i]+p)%p);
  252. ans=(ans+f[i]*g[i][0][all+1])%p;
  253. }
  254. return ans;
  255. }
  256. int main()
  257. {
  258. open("b");
  259. scanf("%s%s",l+1,r+1);
  260. scanf("%d%d%d",&m,&s1,&s2);
  261. init();
  262. ll ans1=solve(l,0);
  263. ll ans2=solve(r,1);
  264. ll ans=ans2-ans1;
  265. ans=(ans%p+p)%p;
  266. printf("%lld\n",ans);
  267. return 0;
  268. }

【XSY2745】装饰地板 状压DP 特征多项式的更多相关文章

  1. [CSP-S模拟测试]:装饰(状压DP)

    题目传送门(内部题114) 输入格式 第一行一个正整数$n$. 接下来一行$n-1$个正整数,第$i$个数为$f_{i+1}$. 接下来一行$n$个数,若第$i$个数为$0$则表示林先森希望$i$号点 ...

  2. POJ 2411 Mondriaan's Dream -- 状压DP

    题目:Mondriaan's Dream 链接:http://poj.org/problem?id=2411 题意:用 1*2 的瓷砖去填 n*m 的地板,问有多少种填法. 思路: 很久很久以前便做过 ...

  3. 状压DP天秀

    状压DP,依靠的是把状态用某种压缩方式表示出来进而DP,大多数时候是二进制状压. 直接看例题吧. 一双木棋     九尾狐吃棉花糖     islands and bridges 愤怒的小鸟   芯片 ...

  4. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  5. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  6. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  7. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  8. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

  9. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

随机推荐

  1. Django signals 信号作用及用法说明

    参考:https://docs.djangoproject.com/en/1.11/ref/signals/ 1.Model signals django.db.models.signales 作用于 ...

  2. vue 饿了么项目笔记

    vue 饿了么项目 1.图标字体引用 链接 2.scss 二三倍图切换 1像素边框 链接 3.better-scroll 4.布局 商品主页面 <div id="app"&g ...

  3. python中Metaclass的理解

    今天在学习<python3爬虫开发实战>中看到这样一段代码3 class ProxyMetaclass(type): def __new__(cls, name, bases, attrs ...

  4. 工作时间看股票:采用Excel RTD技术获取和讯网的实时股票行情及深沪港最新指数

    本文地址:http://www.cnblogs.com/Charltsing/p/RTD.html QQ:564955427 在Excel里面获取实时数据大概有几种方式:1.定时器+函数2.DDE3. ...

  5. vue-lazyload简单使用

    vue-lazyload简单使用 npm地址:https://www.npmjs.com/package/vue-lazyload github地址:https://github.com/hilong ...

  6. java 浅拷贝和深拷贝 对象克隆clone

    分一下几点讨论: 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 一:为什么要克隆? 大家先思考一个问题,为什么需要克隆对象?直接new一个对象不行吗? 答案是:克隆的对象可能包 ...

  7. Azure系列2.1.6 —— BlobProperties

    (小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...

  8. 剑指offer(17)层次遍历树

    题目: 从上往下打印出二叉树的每个节点,同层节点从左至右打印. public class Solution { ArrayList<Integer> list = new ArrayLis ...

  9. Your branch is ahead of 'origin/master' by 2 commits.

    遇到这种问题,表示在你之前已经有2个commit而没有push到远程分支上,所以需要先git push origin **将本地分支提到远程仓库.也可以直接git reset --hard HEAD~ ...

  10. MySQL索引管理及执行计划

    一.索引介绍 二.explain详解 三.建立索引的原则(规范)