ACM-ICPC 2018 焦作赛区网络预赛- L:Poor God Water(BM模板/矩阵快速幂)
God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells him that some sequence of eating will make them poisonous.
Every hour, God Water will eat one kind of food among meat, fish and chocolate. If there are 3 continuous hours when he eats only one kind of food, he will be unhappy. Besides, if there are 3 continuous hours when he eats all kinds of those, with chocolate at the middle hour, it will be dangerous. Moreover, if there are 3 continuous hours when he eats meat or fish at the middle hour, with chocolate at other two hours, it will also be dangerous.
Now, you are the doctor. Can you find out how many different kinds of diet that can make God Water happy and safe during N hours? Two kinds of diet are considered the same if they share the same kind of food at the same hour. The answer may be very large, so you only need to give out the answer module 1000000007.
Input
The fist line puts an integer T that shows the number of test cases. (T≤1000)
Each of the next T lines contains an integer N that shows the number of hours. (1≤N≤1010)
Output
For each test case, output a single line containing the answer.
样例输入
3
3
4
15
样例输出
20
46
435170
题目来源
题意
God Water喜欢吃肉,鱼和巧克力。但是不能连着三小时吃同一种食物,如果连着三个小时吃的食物不一样,那么中间那个小时不能吃巧克力,如果中间那个小时没有吃巧克力,那么第一和第三小时都不能吃巧克力
设:(1)巧克力 (2)鱼 (3)肉
则不符合题意的排列有:111 222 333 213 312 121 131
求n个小时一共有多少种不同的吃食物的方法
思路
DP学长用暴力打出来了前二十项的表,然后得到了一个从第六项开始的递退公式:a[i]=2*a[i-1]-a[i-2]+3*a[i-3]+2*a[i-4]
然后听说BM模板可以直接求任意的线性递推式的任意项,就百度抄了dls的DM模板,学长们是用矩阵快速幂写的
//下面是代码
学长打表用的代码
#pragma GCC optimize ("O3")
#pragma GCC optimize ("O2")
#include <bits/stdc++.h>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define met(s) memset(s, 0, sizeof(s))
#define RR (LL + 1)
typedef long long LL;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<LL, LL> pii;
const int INF = 0x3f3f3f3f;
const ull TOP = (ull)1e17;
const LL MOD = 1e9 + 7;
const int MAXN = 1e5 + 20;
int a[MAXN];
int T, n, ans;
void dfs(int x) {
if(x >= 3) {
if(a[x - 2] == 1) {
if(a[x - 1] == 1 && a[x] == 1) return ;
if(a[x - 1] == 0 && a[x] == 2) return ;
}
else if(a[x - 2] == 2) {
if(a[x - 1] == 2 && a[x] == 2) return ;
if(a[x - 1] == 0 && a[x] == 1) return ;
}
else {
if(a[x - 1] == 0 && a[x] == 0) return ;
if(a[x - 1] == 1 && a[x] == 0) return ;
if(a[x - 1] == 2 && a[x] == 0) return ;
}
}
if(x == n) {
ans++;
return ;
}
for(int i = 0; i < 3; ++i) {
a[x + 1] = i;
dfs(x + 1);
}
}
int main() {
for(int i = 1; i <= 20; ++i) {
ans = 0;
n = i;
dfs(0);
printf("{%d,%d}\n", i, ans);
}
return 0;
}
AC代码
BM模板
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cassert>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0);
for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int _;
ll n;
namespace linear_seq {
const int N=10010;
ll res[N],base[N],_c[N],_md[N];
vector<int> Md;
void mul(ll *a,ll *b,int k) {
rep(i,0,k+k) _c[i]=0;
rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
for (int i=k+k-1;i>=k;i--) if (_c[i])
rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
rep(i,0,k) a[i]=_c[i];
}
int solve(ll n,VI a,VI b) {
ll ans=0,pnt=0;
int k=SZ(a);
assert(SZ(a)==SZ(b));
rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
Md.clear();
rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
rep(i,0,k) res[i]=base[i]=0;
res[0]=1;
while ((1ll<<pnt)<=n) pnt++;
for (int p=pnt;p>=0;p--) {
mul(res,res,k);
if ((n>>p)&1) {
for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
}
}
rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
if (ans<0) ans+=mod;
return ans;
}
VI BM(VI s) {
VI C(1,1),B(1,1);
int L=0,m=1,b=1;
rep(n,0,SZ(s)) {
ll d=0;
rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
if (d==0) ++m;
else if (2*L<=n) {
VI T=C;
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m) C.pb(0);
rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
L=n+1-L; B=T; b=d; m=1;
} else {
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m) C.pb(0);
rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
++m;
}
}
return C;
}
int gao(VI a,ll n) {
VI c=BM(a);
c.erase(c.begin());
rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
}
};
int main() {
scanf("%d",&_);
while(_--)
{
vector<int>v;
v.push_back(3);
v.push_back(9);
v.push_back(20);
v.push_back(46);
v.push_back(106);
v.push_back(244);
v.push_back(560);
v.push_back(1286);
v.push_back(2956);
v.push_back(6794);
v.push_back(15610);
v.push_back(35866);
v.push_back(82416);
scanf("%lld",&n);
printf("%d\n",linear_seq::gao(v,n-1));
}
}
矩阵快速幂
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1000000007;
struct mat {
LL mapp[4][4];
};
mat mat_pow(mat A, mat B) {
mat C;
memset(C.mapp, 0, sizeof(C.mapp));
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
for(int k = 0; k < 4; k++) {
C.mapp[i][k] = (C.mapp[i][k] + A.mapp[i][j] * B.mapp[j][k]) % mod;
}
}
}
return C;
}
mat mat_mul(mat A, LL b) {
mat ans;
memset(ans.mapp, 0, sizeof(ans.mapp));
ans.mapp[0][0] = ans.mapp[1][1] = ans.mapp[2][2] = ans.mapp[3][3] = 1;
while(b) {
if(b & 1)
ans = mat_pow(ans, A);
A = mat_pow(A, A);
b >>= 1;
}
return ans;
}
LL f[] = {3, 9, 20, 46, 106, 244, 560, 1286, 2956, 6794, 15610, 35866, 82416, 189384, 435170, 999936, 2297686, 5279714, 12131890};
int main() {
int T; LL n; mat A, ans;
ans.mapp[0][0] = 2, ans.mapp[0][1] = -1, ans.mapp[0][2] = 3, ans.mapp[0][3] = 2;
ans.mapp[1][0] = 1, ans.mapp[1][1] = 0, ans.mapp[1][2] = 0, ans.mapp[1][3] = 0;
ans.mapp[2][0] = 0, ans.mapp[2][1] = 1, ans.mapp[2][2] = 0, ans.mapp[2][3] = 0;
ans.mapp[3][0] = 0, ans.mapp[3][1] = 0, ans.mapp[3][2] = 1, ans.mapp[3][3] = 0;
memset(A.mapp, 0, sizeof(A.mapp));
A.mapp[0][0] = 106, A.mapp[1][0] = 46, A.mapp[2][0] = 20, A.mapp[3][0] = 9;
scanf("%d", &T);
while(T--) {
scanf("%lld", &n);
if(n <= 10) {
printf("%lld\n", f[n - 1]);
continue;
}
mat B = mat_mul(ans, n - 5);
B = mat_pow(B, A);
printf("%lld\n", B.mapp[0][0] % mod);
}
return 0;
}
ACM-ICPC 2018 焦作赛区网络预赛- L:Poor God Water(BM模板/矩阵快速幂)的更多相关文章
- ACM-ICPC 2018 焦作赛区网络预赛 L Poor God Water(矩阵快速幂,BM)
https://nanti.jisuanke.com/t/31721 题意 有肉,鱼,巧克力三种食物,有几种禁忌,对于连续的三个食物:1.这三个食物不能都相同:2.若三种食物都有的情况,巧克力不能在中 ...
- ACM-ICPC 2018 焦作赛区网络预赛 L 题 Poor God Water
God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells him t ...
- ACM-ICPC 2018 焦作赛区网络预赛 L:Poor God Water(矩阵快速幂)
God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells him t ...
- ACM-ICPC 2018 焦作赛区网络预赛- G:Give Candies(费马小定理,快速幂)
There are N children in kindergarten. Miss Li bought them NNN candies. To make the process more inte ...
- ACM-ICPC 2018 焦作赛区网络预赛
这场打得还是比较爽的,但是队友差一点就再过一题,还是难受啊. 每天都有新的难过 A. Magic Mirror Jessie has a magic mirror. Every morning she ...
- ACM-ICPC 2018 焦作赛区网络预赛J题 Participate in E-sports
Jessie and Justin want to participate in e-sports. E-sports contain many games, but they don't know ...
- ACM-ICPC 2018 焦作赛区网络预赛 K题 Transport Ship
There are NN different kinds of transport ships on the port. The i^{th}ith kind of ship can carry th ...
- ACM-ICPC 2018 焦作赛区网络预赛 I题 Save the Room
Bob is a sorcerer. He lives in a cuboid room which has a length of AA, a width of BB and a height of ...
- ACM-ICPC 2018 焦作赛区网络预赛 H题 String and Times(SAM)
Now you have a string consists of uppercase letters, two integers AA and BB. We call a substring won ...
随机推荐
- Uboot启动流程分析(转载)
最近一段时间一直在做uboot移植相关的工作,需要将uboot-2016-7移植到单位设计的ARMv7的处理器上.正好元旦放假三天闲来无事,有段完整的时间来整理下最近的工作成果.之前在学习uboot时 ...
- 个人前端学习路线图与github优秀前端开发者的路线图推荐
1.个人目前学习的路线图 2.github优秀前端开发者的路线图推荐 打开github首页,在搜索框输入developer-roadmap,搜索github前端路线图 选择kamranahmedse/ ...
- Unity3D中的射线与碰撞检测代码
两种不同写法的射线检测 1.获取鼠标点击的物体 if (Input.GetMouseButtonDown(0)) { Ray ray = MainCamera.ScreenPointToRay(Inp ...
- 双向链表--首页大小不一卡片排序 --- react --- js
1.4中类型(grid_type)的卡片:1:大方块:2:竖长块:3:横长块:4:小方块 var order = 0; // 创建链表 function List(head) { this.head ...
- 在学习DRF之前
学习DRF之前~~~ 在学习DRF之前~我们要先复习一些知识点~~ FBV和CBV 学习Django的时候~我们已经学习过了CBV以及FBV~~我们来复习一下~~ 什么是FBV和CBV呢~~ FB ...
- Docker Kubernetes(K8s)简介
入职了新公司,使用了Docker和K8s,需要有一个基础的了解,对网络上相关信息进行了简单总结. 一Docker 1简介: Docker 将应用程序与该程序的依赖,打包在一个文件里面.运行这个文件,就 ...
- 使用 DirectX 创建 3D 图形
官方链接 https://msdn.microsoft.com/zh-cn/library/windows/desktop/hh465137.aspx 使用 Windows 运行时初始化 Dire ...
- webstorm安装流程
第一步:双击安装目录 修改安装目录 尽量不要放在C盘 第二步: 把汉化包 直接复制文件到WebStorm安装目录中lib文件夹中即可,重新打开WebStorm就可以了
- crontab的定时任务实例
实例1:每1分钟执行一次myCommand * * * * * myCommand 实例2:每小时的第3和第15分钟执行 3,15 * * * * myCommand 实例3:在上午8点到11点的第3 ...
- SpringMVC实现从磁盘中下载文件
除了文件的上传我们还需要从磁盘下载 实现文件的下载只要编写一个控制器,完成读写操作和响应头和数据类型的设置就可以了 下面演示的是从G盘imgs文件夹中下载文件 具体代码如下 package com.c ...