食物(矩阵快速幂)(DP)

这个题。。我们可以想到用递推写!!qwq(好吧,其实我的DP水平不高啊qwq)
就是我们以两个为单位(一共九种组合情况),然后往后面推下一位的情况。
通过手动模拟,我们可以找到它们之间的递推关系(详见代码)
先放上我的暴力代码。。。。(60分)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define mod 1000000007
using namespace std;
long long f[2][10];
int t,cnt=1;
struct Node{int id,que;long long ans=0;}node[1010];
bool cmp1(struct Node x,struct Node y)
{
if(x.que<y.que) return 1;
else return 0;
}
bool cmp2(struct Node x,struct Node y)
{
if(x.id<y.id) return 1;
else return 0;
}
inline int read()
{
int f=1,x=0; char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int main()
{
freopen("food.in","r",stdin);
freopen("food.out","w",stdout);
t=read();
//scanf("%d",&t);
for(int i=1;i<=t;i++) node[i].que=read(),node[i].id=i;
//scanf("%d",&node[i].que),node[i].id=i;
sort(node+1,node+1+t,cmp1);
//cout<<endl;
//for(int i=1;i<=t;i++)
// printf("%d ",node[i].que);
f[0][1]=2;
f[0][2]=3;
f[0][3]=2;
f[0][4]=3;
f[0][5]=2;
f[0][6]=2;
f[0][7]=2;
f[0][8]=2;
f[0][9]=2;
while(node[cnt].que==1) node[cnt].ans=3,cnt++;
while(node[cnt].que==2) node[cnt].ans=9,cnt++;
while(node[cnt].que==3) node[cnt].ans=20,cnt++;
for(int i=1;i<=node[t].que-3;i++)
{
f[1][1]=(f[0][4]+f[0][8])%mod;
f[1][2]=(f[0][1]+f[0][4]+f[0][8])%mod;
f[1][3]=(f[0][1]+f[0][4])%mod;
f[1][4]=(f[0][2]+f[0][5]+f[0][7])%mod;
f[1][5]=(f[0][2]+f[0][7])%mod;
f[1][6]=(f[0][2]+f[0][5])%mod;
f[1][7]=(f[0][6]+f[0][9])%mod;
f[1][8]=(f[0][3]+f[0][9])%mod;
f[1][9]=(f[0][3]+f[0][6])%mod;
//for(int j=1;j<10;j++)
// printf("f[1][%d]=%lld\n",j,f[1][j]);
for(int j=1;j<10;j++)
swap(f[0][j],f[1][j]);
while(i==node[cnt].que-3)
{
long long ans=0;
for(int j=1;j<10;j++)
ans=(ans+f[0][j])%mod;
node[cnt].ans=ans;
// cout<<"ans="<<ans<<endl;
cnt++;
}
}
sort(node+1,node+1+t,cmp2);
for(int i=1;i<=t;i++)
printf("%lld\n",node[i].ans%mod);
return 0;
}
然后我们看到数据范围。。。好大呀qwq线性算法肯定会T啊qwq,那。。。。写矩阵加速吧!qwq
其实有了暴力程序之后矩阵很好写(就是把对应的行和列上面的数设成1,然后做一次矩阵乘法就相当于一次转移。
详见代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define mod 1000000007
using namespace std;
int t;
int f[10];
struct Node{long long m[10][10];}node;
inline Node mul(Node x,Node y)
{
Node cur;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
cur.m[i][j]=0;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
for(int k=1;k<=9;k++)
cur.m[i][j]=(cur.m[i][j]+x.m[i][k]*y.m[k][j])%mod;
return cur;
}
inline void solve(Node x)
{
int cur[10];
memset(cur,0,sizeof(cur));
for(int j=1;j<=9;j++)
for(int k=1;k<=9;k++)
cur[j]=(cur[j]+f[k]*x.m[k][j])%mod;
for(int i=1;i<=9;i++)
f[i]=cur[i];
}
int main()
{
scanf("%d",&t);
while(t--)
{
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
node.m[i][j]=0;
node.m[1][4]=1,node.m[1][8]=1;
node.m[2][1]=1,node.m[2][4]=1,node.m[2][8]=1;
node.m[3][1]=1,node.m[3][4]=1;
node.m[4][2]=1,node.m[4][5]=1,node.m[4][7]=1;
node.m[5][2]=1,node.m[5][7]=1;
node.m[6][2]=1,node.m[6][5]=1;
node.m[7][6]=1,node.m[7][9]=1;
node.m[8][3]=1,node.m[8][9]=1;
node.m[9][3]=1,node.m[9][6]=1;
memset(f,0,sizeof(f));
int n;
for(int i=1;i<=9;i++) f[i]=1;
scanf("%d",&n);
n-=2;
while(n)
{
if(n&1) solve(node);
node=mul(node,node);
n>>=1;
}
long long ans=0;
for(int i=1;i<=9;i++)
ans=(ans+f[i])%mod;
printf("%lld\n",ans%mod);
}
return 0;
}
食物(矩阵快速幂)(DP)的更多相关文章
- codeforces 691E 矩阵快速幂+dp
传送门:https://codeforces.com/contest/691/problem/E 题意:给定长度为n的序列,从序列中选择k个数(可以重复选择),使得得到的排列满足xi与xi+1异或的二 ...
- P1357 花园 (矩阵快速幂+ DP)
题意:一个只含字母C和P的环形串 求长度为n且每m个连续字符不含有超过k个C的方案数 m <= 5 n <= 1e15 题解:用一个m位二进制表示状态 转移很好想 但是这个题是用矩阵快速 ...
- BZOJ1009 矩阵快速幂+DP+KMP
Problem 1009. -- [HNOI2008]GT考试 1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: ...
- Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP
题意: 给一个$n$点$m$边的连通图 每个边有一个权值$d$ 当且仅当当前走过的步数$\ge d$时 才可以走这条边 问从节点$1$到节点$n$的最短路 好神的一道题 直接写做法喽 首先我们对边按$ ...
- COJ 1208 矩阵快速幂DP
题目大意: f(i) 是一个斐波那契数列 , 求sum(f(i)^k)的总和 由于n极大,所以考虑矩阵快速幂加速 我们要求解最后的sum[n] 首先我们需要思考 sum[n] = sum[n-1] + ...
- Codeforces 954 dijsktra 离散化矩阵快速幂DP 前缀和二分check
A B C D 给你一个联通图 给定S,T 要求你加一条边使得ST的最短距离不会减少 问你有多少种方法 因为N<=1000 所以N^2枚举边数 迪杰斯特拉两次 求出Sdis 和 Tdis 如果d ...
- Codeforces 989E A Trance of Nightfall 矩阵快速幂+DP
题意:二维平面上右一点集$S$,共$n$个元素,开始位于平面上任意点$P$,$P$不一定属于$S$,每次操作为选一条至少包含$S$中两个元素和当前位置$P$的直线,每条直线选取概率相同,同一直线上每个 ...
- BZOJ1009: [HNOI2008]GT考试 (矩阵快速幂 + DP)
题意:求一个长度为n的数字字符串 (n <= 1e9) 不出现子串s的方案数 题解:用f i,j表示长度为i匹配到在子串j的答案 用kmp的失配函数预处理一下 然后这个转移每一个都是一样的 所以 ...
- bzoj2004 矩阵快速幂优化状压dp
https://www.lydsy.com/JudgeOnline/problem.php?id=2004 以前只会状压dp和矩阵快速幂dp,没想到一道题还能组合起来一起用,算法竞赛真是奥妙重重 小Z ...
- ZZNU 2182 矩阵dp (矩阵快速幂+递推式 || 杜教BM)
题目链接:http://47.93.249.116/problem.php?id=2182 题目描述 河神喜欢吃零食,有三种最喜欢的零食,鱼干,猪肉脯,巧克力.他每小时会选择一种吃一包. 不幸的是,医 ...
随机推荐
- MyBatis 学习记录3 MapperMethod类
主题 之前学习了一下MapperProxy的生产过程,自定义Mapper类的对象是通过动态代理生产的,调用自定义方法的时候实际上是调用了MapperMethod的execute方法:mapperMet ...
- UNITY中使用不安全代码的相关设置
必须执行以下三个步骤 1,在工程属性中设置:属性-生成-允许不安全代码 2,在Assets目录下增加 smcs.rsp(若打包设置中使用了.net 2.0 subset)或 gmcs.rsp(若打包设 ...
- Hibernate多对多关联映射的HQL中的in条件查询问题
群里有朋友求解一个问题,高分求一条HQL多对多查询语句 . 问题描述见 http://topic.csdn.net/u/20090621/16/4eac6fe0-bf3e-422e-a697-f758 ...
- default of c#
[default of c#] 在泛型类和泛型方法中产生的一个问题是,在预先未知以下情况时,如何将默认值分配给参数化类型 T: T 是引用类型还是值类型. 如果 T 为值类型,则它是数值还是结构. 给 ...
- 高性能Web服务器Nginx的配置与部署研究(13)应用模块之Memcached模块+Proxy_Cache双层缓存模式
通过<高性能Web服务器Nginx的配置与部署研究——(11)应用模块之Memcached模块的两大应用场景>一文,我们知道Nginx从Memcached读取数据的方式,如果命中,那么效率 ...
- APP安全之代码混淆防止反编译查看真实的头文件函数声明
现在有的公司对自己的爱屁屁(APP)安全上有重视,所以本篇讲一下代码混淆,即使别人反编译出来,也看不出来头文件的信息. 上菜: 1.首先安装class-dump,下载地址:http://steveny ...
- opencv cv::imageshow 不加waitKey()不能显示图片
官方解释是highgui 没有给imshow绘制处理的时间.需要在imshow添加waitKey() waitKey()单位是ms
- code3728 联合权值
一开始暴搜,超时3个点... 后来看了题解: 首先,两个点的距离为2当且仅当它们都与一个点直接相连 反过来说,一个点所有的出边的终点都是互相距离2的(最大值可以依靠这个方法,前向星处理的时候将每个点的 ...
- JSON_UNESCAPED_UNICODE
JSON_UNESCAPED_UNICODE(中文不转为unicode)
- AutoComplete的extraParams动态传递参数
AutoComplete可利用extraParams传递参数,如 extraParams:{para1:'参数1',para2:'参数2'} 但是,如需动态取值作为参数值时却无法达到期望目的,可改为配 ...