题目大意

  你有\(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定理&倍增取模

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<utility>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
typedef vector<ll> poly;
const ll p=998244353;
ll fp(ll a,ll b)
{
ll s=1;
for(;b;b>>=1,a=a*a%p)
if(b&1)
s=s*a%p;
return s;
}
struct matrix
{
ll a[130][130];
int n,m;
matrix()
{
memset(a,0,sizeof a);
n=m=0;
}
ll *operator [](int x)
{
return a[x];
}
};
matrix operator *(matrix a,matrix b)
{
matrix c;
c.n=a.n;
c.m=b.m;
for(int i=0;i<a.n;i++)
for(int j=0;j<a.m;j++)
{
ll s=0;
for(int k=0;k<b.m;k++)
s=(s+a[i][k]*b[k][j])%p;
c[i][j]=s;
}
return c;
}
namespace yww
{
poly f[200];
void add(poly &a,poly b,ll s1,ll s2)
{
int n=b.size();
while(int(a.size())<n+1)
a.push_back(0);
for(int i=0;i<n;i++)
{
a[i]=(a[i]+b[i]*s2)%p;
a[i+1]=(a[i+1]+b[i]*s1)%p;
}
while(a.back()==0)
a.pop_back();
}
poly getpoly(matrix a,int n)
{
for(int i=0;i<=n;i++)
{
int j;
for(j=i+1;j<=n;j++)
if(a[j][i])
break;
if(j>n)
continue;
if(j!=i+1)
{
for(int k=i;k<=n;k++)
swap(a[i+1][k],a[j][k]);
for(int k=0;k<=n;k++)
swap(a[k][i+1],a[k][j]);
}
for(int j=i+2;j<=n;j++)
if(a[j][i])
{
ll v=fp(a[i+1][i],p-2)*a[j][i]%p;
for(int k=i;k<=n;k++)
a[j][k]=(a[j][k]-a[i+1][k]*v)%p;
for(int k=0;k<=n;k++)
a[k][i+1]=(a[k][i+1]+a[k][j]*v)%p;
}
}
f[n+1].push_back(1);
for(int i=n;i>=0;i--)
{
add(f[i],f[i+1],1,-a[i][i]);
ll v=1;
for(int j=i+2;j<=n+1;j++)
{
v=v*a[j-1][j-2]%p;
add(f[i],f[j],0,-v*a[i][j-1]%p);
}
}
return f[0];
}
}
matrix a;
int m,s1,s2,all;
void dfs(int x,int a1,int a2,ll s)
{
if(x>m+1)
return;
if(x>m)
{
a[all^a1][a2]=(a[all^a1][a2]+s)%p;
return;
}
dfs(x+1,a1,a2,s);
dfs(x+1,a1|(1<<(x-1)),a2|(1<<(x-1)),s*s1%p);
dfs(x+2,a1,a2|(3<<(x-1)),s*s2%p);
}
poly aa;
int len;
//poly f[20];
matrix g[200];
poly operator *(poly a,poly b)
{
int n=a.size()-1;
int m=b.size()-1;
poly c(n+m+1);
for(int j=0;j<=m;j++)
if(b[j])
for(int i=0;i<=n;i++)
c[i+j]=(c[i+j]+a[i]*b[j])%p;
return c;
}
poly operator %(poly a,poly b)
{
int n=a.size()-1;
int m=b.size()-1;
for(int i=n;i>=m;i--)
if(a[i])
{
ll v=a[i];
for(int j=0;j<=m;j++)
a[i-m+j]=(a[i-m+j]-b[j]*v)%p;
}
while(!a.back())
a.pop_back();
return a;
}
poly a1;
void init()
{
all=(1<<m)-1;
dfs(1,0,0,1);
a[all][all+1]=1;
a[all+1][all+1]=1;
a.n=a.m=all+2;
aa=yww::getpoly(a,all+1);
len=aa.size()-1;
// for(int i=0;i<=len;i++)
// c[i]=aa[i];
// f[0].push_back(1);
// for(int i=1;i<=9;i++)
// {
// f[i].resize(i+1);
// f[i][i]=1;
// f[i]=f[i]%aa;
//// for(auto v:f[i])
//// printf("%lld ",(v+p)%p);
//// printf("\n");
// }
g[0][0][all]=1;
g[0].n=1;
g[0].m=a.n;
for(int i=1;i<len;i++)
{
g[i]=g[i-1]*a;
// printf("%lld\n",(g[i][0][all+1]+p)%p);
}
a1.resize(2);
a1[0]=0;
a1[1]=1;
a1=a1%aa;
}
char l[10010],r[10010];
int e[100010];
int bit[100010];
poly f;
void calc(int n)
{
if(!n)
return;
calc(n-1);
f=f*f%aa;
if(bit[n])
f=f*a1%aa;
}
int solve(char *str,int b)
{
int n=strlen(str+1);
memset(e,0,sizeof e);
for(int i=1;i<=n;i++)
e[i]=str[n-i+1]-'0';
e[1]+=b;
int i;
for(i=1;e[i]>=10;i++)
{
e[i+1]+=e[i]/10;
e[i]%=10;
}
n=max(n,i);
memset(bit,0,sizeof bit);
int k=1;
for(int i=n;i>=1;i--)
{
int s=0;
int j;
for(j=1;j<=k||s;j++)
{
s+=bit[j]*10;
bit[j]=s&1;
s>>=1;
}
k=max(k,j);
bit[1]+=e[i];
for(j=1;bit[j]>=2;j++)
{
bit[j+1]+=bit[j]>>1;
bit[j]&=1;
}
k=max(k,j);
}
f.clear();
f.push_back(1);
reverse(bit+1,bit+k+1);
calc(k);
ll ans=0;
for(int i=0;i<f.size()&&i<len;i++)
{
// printf("%lld\n",(f[i]+p)%p);
ans=(ans+f[i]*g[i][0][all+1])%p;
}
return ans;
}
int main()
{
open("b");
scanf("%s%s",l+1,r+1);
scanf("%d%d%d",&m,&s1,&s2);
init();
ll ans1=solve(l,0);
ll ans2=solve(r,1);
ll ans=ans2-ans1;
ans=(ans%p+p)%p;
printf("%lld\n",ans);
return 0;
}

【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. 01-HTML介绍

    1.WEB标准 web准备介绍: w3c:万维网联盟组织,用来制定web标准的机构(组织) web标准:制作网页遵循的规范 web准备规范的分类:结构标准.表现标准.行为标准. 结构:html.表示: ...

  2. Servlet 快速概览

    目录 生命周期 web.xml 获取表单数据(设置请求的编码格式) 返回响应内容(设置响应的编码格式) 结合前两点,总结基本模板 获取请求协议头部信息 设置响应头部信息 使用过滤器 在web.xml中 ...

  3. 同事写得Python对页面压测脚本

    #!/usr/bin/env python # *-* coding:utf-8 *-* import threading import requests import time # headers ...

  4. 四、Object.defineProperty总结

    Object.defineProperty() 参考:https://segmentfault.com/a/1190000007434923 定义: 方法会直接在一个对象上定义一个新属性,或者修改一个 ...

  5. Cookie-parser

    let express = require('express'); let app =new express(); // 引入cookie-parser; let cookieParser = req ...

  6. C# Note10: AutoComplete TextBox in WPF

    参考: 1.https://stackoverflow.com/questions/950770/autocomplete-textbox-in-wpf 2.AutoCompleteBox的使用(实现 ...

  7. 剑指Offer(9)

    题目: 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 解法: 要考虑到底数为0,指数为负数的情况,这道题主要考的是对边界值的思考. p ...

  8. w3c JS测试

    到W3c的js测试里面溜达了一圈: 做错了几道题: 外部脚本必须包含<script>标签吗? 否!! 这里的外部脚本是指xx.js这个文件,在文件中写js代码是不需要包含script标签的 ...

  9. redis 中主从、哨兵和集群分片模式这三个有什么区别 ?

    集群分片 比如 5主5从,也就是说 数据过来之后会均匀的分配到5台服务器上面,5台服务器上面的数据是不同的,但是每个服务器都有一个从服务器,上面的数据跟这一台主服务器的数据是一样的: 也就是说,对于这 ...

  10. Python自动化运维ansible从入门到精通

    1. 下载安装 在windows下安装ansible: