五校联考R1 Day1T3 平面图planar(递推 矩阵快速幂)
我们可以把棱柱拆成有\(n\)条高的矩形,尝试递推。
在计算的过程中,第\(i\)列(\(i\neq n\))只与\(i-1\)列有关,称\(i-1\)列的上面/下面为左上/左下,第\(i\)列的上面/下面为右上/右下。
我们可以发现,右上可选的颜色数与左上和右下是否同色有关,右下同理,那就记\(f[i][0/1][0/1]\)表示左上与右下是否同色,左下与右上是否同色。
但是第\(n\)列和第\(1\)列不能同色,最后怎么算答案?
不知道第\(n\)列状态算不了,所以我们还要记第\(i\)列的上/下是否与第\(1\)列的上&下同色。称\(1\)列的上面/下面为左上/左下,我们发现这样只记与第\(1\)列的情况就可以知道第\(i-1\)列怎么转移到第i列了(这谁发现了。。)。
那么 \(f[i][0/1/2][0/1/2]\) 表示到第\(i\)列,右上的颜色 与左上、左下都不相同/与左上相同/与左下相同;右下的颜色 与左上、左下都不相同/与左上相同/与左下相同 的方案数。
最后的答案就是\(\sum f[n][j\neq 1][k\neq 2]\)(就是\(f[n+1][1][2]\))。可以递推啦。
改成矩阵快速幂就可以AC了。这个矩阵还算好推。
有两组状态是对称的,可以把状态压成5*5?不过没什么用。
转移好恶心啊。
65分递推:
#include <cstdio>
#include <algorithm>
#define mod (1000000007)
typedef long long LL;
const int N=1e6+5;
LL n,m,f[N][3][3];
inline LL FP(LL x,LL k)
{
LL t=1; //x%=mod;
for(; k; k>>=1,x=x*x%mod)
if(k&1) t=t*x%mod;
return t;
}
int main()
{
freopen("planar.in","r",stdin);
freopen("planar.out","w",stdout);
scanf("%lld%lld",&n,&m);
if(m==2) return putchar(n&1?'0':'2'),0;
f[1][1][2]=m*(m-1)%mod;
LL m3=(m-3)*(m-3)%mod, m2=(m-2)*(m-2)%mod, m23=(m-2)*(m-3)%mod, m34=(m3-m+4+mod)%mod;
for(int i=2; i<=n; ++i)
{//LONG_LONG_MAX=9e18 > 4e9*1e9
// LL (*pre)[3]=f[i-1];//慢了smg
f[i][0][0]=(f[i-1][0][0]*m34%mod+
(f[i-1][0][1]+f[i-1][0][2]+f[i-1][1][0]+f[i-1][2][0])*m3%mod+
(f[i-1][1][2]+f[i-1][2][1])*m23%mod)%mod;
f[i][0][1]=((f[i-1][0][0]+f[i-1][0][2])*(m-3)%mod+
(f[i-1][1][0]+f[i-1][2][0]+f[i-1][1][2])*(m-2)%mod)%mod;
f[i][1][0]=((f[i-1][0][0]+f[i-1][2][0])*(m-3)%mod+
(f[i-1][0][1]+f[i-1][0][2]+f[i-1][2][1])*(m-2)%mod)%mod;
f[i][0][2]=((f[i-1][0][0]+f[i-1][0][1])*(m-3)%mod+
(f[i-1][1][0]+f[i-1][2][0]+f[i-1][2][1])*(m-2)%mod)%mod;
f[i][2][0]=((f[i-1][0][0]+f[i-1][1][0])*(m-3)%mod+
(f[i-1][0][1]+f[i-1][0][2]+f[i-1][1][2])*(m-2)%mod)%mod;
f[i][1][2]=(f[i-1][0][0]+f[i-1][0][1]+f[i-1][2][0]+f[i-1][2][1])%mod;
f[i][2][1]=(f[i-1][0][0]+f[i-1][0][2]+f[i-1][1][0]+f[i-1][1][2])%mod;
}
printf("%lld\n",(f[n][0][0]+f[n][0][1]+f[n][2][0]+f[n][2][1])%mod);
return 0;
}
100 矩阵快速幂:
//O(49)推矩阵好恶心啊。
#include <cstdio>
#include <algorithm>
#define mod (1000000007)
typedef long long LL;
const int N=1e6+5;
struct Matrix
{
LL a[7][7];
Matrix operator *(const Matrix &x)
{
Matrix res;
for(int i=0; i<7; ++i)
for(int j=0; j<7; ++j)
{
LL tmp=0;
for(int k=0; k<7; ++k)
tmp+=a[i][k]*x.a[k][j]%mod;
res.a[i][j]=tmp%mod;
}
return res;
}
}A;
inline Matrix FP(Matrix x,LL k)
{
Matrix t=x;
for(--k; k; k>>=1,x=x*x)
if(k&1) t=t*x;
return t;
}
int main()
{//[(7*7)^n]*(7*1) 正好转移n次得到f[n+1]。
freopen("planar.in","r",stdin);
freopen("planar.out","w",stdout);
LL n,m; scanf("%lld%lld",&n,&m);
if(m==2) return putchar(n&1?'0':'2'),0;
/*
0: (0,0)
1: (0,1)
2: (0,2)
3: (1,0)
4: (1,2)
5: (2,0)
6: (2,1)
*/
if(m>=4) A.a[0][0]=((m-3)*(m-3)%mod-(m-4)+mod)%mod;
A.a[0][1]=A.a[0][2]=A.a[0][3]=A.a[0][5]=(m-3)*(m-3)%mod;
A.a[0][4]=A.a[0][6]=(m-2)*(m-3)%mod;
A.a[1][0]=A.a[1][2]=A.a[2][0]=A.a[2][1]=A.a[3][0]=A.a[3][5]=A.a[5][0]=A.a[5][3]=m-3;
A.a[1][3]=A.a[1][4]=A.a[1][5]=A.a[2][3]=A.a[2][5]=A.a[2][6]=A.a[3][1]=A.a[3][2]=A.a[3][6]=A.a[5][1]=A.a[5][2]=A.a[5][4]=m-2;
A.a[4][0]=A.a[4][1]=A.a[4][5]=A.a[4][6]=A.a[6][0]=A.a[6][2]=A.a[6][3]=A.a[6][4]=1;
A=FP(A,n);
printf("%lld\n",A.a[4][4]*m%mod*(m-1)%mod);//f[n+1][1][2] = (A^n)[4][j] * Mat={0,0,0,0,m(m-1),0,0}
// f[1][1][2]=m*(m-1)%mod;
// LL m3=(m-3)*(m-3)%mod, m2=(m-2)*(m-2)%mod, m23=(m-2)*(m-3)%mod, m34=(m3-m+4+mod)%mod;
// for(int i=2; i<=n; ++i)
// {//LONG_LONG_MAX=9e18 > 4e9*1e9
// f[i][0][0]=(f[i-1][0][0]*m34%mod+
// (f[i-1][0][1]+f[i-1][0][2]+f[i-1][1][0]+f[i-1][2][0])*m3%mod+
// (f[i-1][1][2]+f[i-1][2][1])*m23%mod)%mod;
//
// f[i][0][1]=((f[i-1][0][0]+f[i-1][0][2])*(m-3)%mod+
// (f[i-1][1][0]+f[i-1][2][0]+f[i-1][1][2])*(m-2)%mod)%mod;
// f[i][1][0]=((f[i-1][0][0]+f[i-1][2][0])*(m-3)%mod+
// (f[i-1][0][1]+f[i-1][0][2]+f[i-1][2][1])*(m-2)%mod)%mod;
//
// f[i][0][2]=((f[i-1][0][0]+f[i-1][0][1])*(m-3)%mod+
// (f[i-1][1][0]+f[i-1][2][0]+f[i-1][2][1])*(m-2)%mod)%mod;
// f[i][2][0]=((f[i-1][0][0]+f[i-1][1][0])*(m-3)%mod+
// (f[i-1][0][1]+f[i-1][0][2]+f[i-1][1][2])*(m-2)%mod)%mod;
//
// f[i][1][2]=(f[i-1][0][0]+f[i-1][0][1]+f[i-1][2][0]+f[i-1][2][1])%mod;
// f[i][2][1]=(f[i-1][0][0]+f[i-1][0][2]+f[i-1][1][0]+f[i-1][1][2])%mod;
// }
return 0;
}
25分的考场代码:
//Subtask?
#include <map>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
//#define rg register
#define mod (1000000007)
typedef long long LL;
const int N=1e6+5;
int m,col[N],pw[N];
LL n,tot,Ans;
std::map<int,bool> vis;
inline LL read()
{
LL now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline LL FP(LL x,LL k)
{
LL t=1; //x%=mod;
for(; k; k>>=1,x=x*x%mod)
if(k&1) t=t*x%mod;
return t;
}
inline LL Pow(LL x,int k)
{
for(k--; k--; x*=x);
return x;
}
inline bool Check(int x,int c)
{
return ((c==col[x-1]&&x!=n+1)||(x>n&&c==col[x-n])||(x==n&&c==col[1])||(x==tot&&c==col[n+1]))^1;
}
void DFS(int x,int s)
{
if(x>tot)
{
if(!vis[s]) ++Ans;
return;
}
for(int i=1; i<=m; ++i)
if(Check(x,i)) col[x]=i, DFS(x+1,s+(i-1)*pw[x-1]), col[x]=-1;
}
namespace Subtask4
{
int f[N][3][3];
LL Calc(int a,int b)
{
for(int i=2; i<=n; ++i)
for(int j=0; j<3; ++j)
for(int k=0; k<3; ++k)
if(j!=k)
{
LL tmp=0;
for(int jj=0; jj<3; ++jj)
if(j!=jj)
for(int kk=0; kk<3; ++kk)
if(k!=kk) tmp+=f[i-1][jj][kk];
f[i][j][k]=(int)(tmp%mod);
// f[i][j][k]=tmp%mod;
// tmp=(j!=0)*((k!=1)*f[i-1][0][1]+(k!=2)*f[i-1][0][2])+(j!=1)*((k!=0)*f[i-1][1][0]+(k!=2)*f[i-1][1][2])+(j!=2)*((k!=0)*f[i-1][2][0]+(k!=1)*f[i-1][2][1]);
}
LL ans=0;
for(int j=0; j<3; ++j)
for(int k=0; k<3; ++k)
if(a!=j && b!=k) ans+=f[n][j][k];
return ans%mod;
}
void Main()
{
// f[1][0][1]=f[1][0][2]=f[1][1][0]=f[1][1][2]=f[1][2][0]=f[1][2][1]=1;
LL ans=0;
for(int a=0; a<3; ++a)
for(int b=0; b<3; ++b)
if(a!=b) f[1][a][b]=1, ans+=Calc(a,b), f[1][a][b]=0;
printf("%d\n",(int)(ans%mod));
}
}
int main()
{
freopen("planar.in","r",stdin);
freopen("planar.out","w",stdout);
// freopen("table.out","w",stdout);
n=read(), tot=n<<1, m=read();
if(m==1) return putchar('0'),0;
if(m==2) return putchar(n&1?'0':'2'),0;
if(n<=4 && m<=4)
{
pw[0]=1, col[0]=-1;
for(int i=1; i<=tot; ++i) pw[i]=pw[i-1]*m, col[i]=-1;
Ans=0, col[1]=1, DFS(2,0), printf("%I64d\n",Ans*m);
return 0;
}
if(m==3) {Subtask4::Main(); return 0;}
putchar('1');
// for(m=3; m<=10; ++m)
// for(n=3; n<=10; ++n)
// if(FP(m,(tot=n<<1)-1)<=5e7)//n<=4 && m<=4
// {
// printf("(%I64d,%d)=",n,m);
// pw[0]=1, col[0]=-1;
// for(int i=1; i<=tot; ++i) pw[i]=pw[i-1]*m, col[i]=-1;
// vis.clear(), Ans=0, col[1]=1, DFS(2,0), printf("%I64d\n",Ans*m);
//// vis.clear(), Ans=0, DFS(1,0), printf("%I64d\n",Ans);
// }
// else break;
return 0;
}
五校联考R1 Day1T3 平面图planar(递推 矩阵快速幂)的更多相关文章
- 五校联考R1 Day2T2 矩阵matrix(容斥)
题目链接 容易想到容斥,但是很恶心,因为要对行和列都容斥,然后行+列又要容斥.. 于是得到\(O(nm\log)\)的做法. 就有70分了: #include <cstdio> #incl ...
- 2019牛客暑期多校训练营(第五场)- B generator 1 (齐次线性递推+矩阵快速幂)
题目链接:https://ac.nowcoder.com/acm/contest/885/B 题意:已知齐次线性式xn=a*xn-1+b*xn-2,已知a,b,x0,x1,求xn,n很大,n<= ...
- 【六省联考2017】组合数问题 题解(矩阵快速幂优化DP)
题目链接 题目大意:求$(\sum\limits_{i=0}^n C_{nk}^{ik+r})\ mod \ p$的值. --------------------- 讲真,一开始看到这个题我都没往DP ...
- 【五校联考1day2】JZOJ2020年8月12日提高组T2 我想大声告诉你
[五校联考1day2]JZOJ2020年8月12日提高组T2 我想大声告诉你 题目 Description 因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一 ...
- 【五校联考1day2】JZOJ2020年8月12日提高组T1 对你的爱深不见底
[五校联考1day2]JZOJ2020年8月12日提高组T1 对你的爱深不见底 题目 Description 出乎意料的是,幸运E 的小R 居然赢了那个游戏.现在欣喜万分的小R 想要写一张明信片给小Y ...
- 【NOIP2016提高A组五校联考4】square
题目 分析 首先,设\(f_{i,j}\)表示最大的以(i,j)为左下角的正方形的边长. 转移显然,\(f_{i,j}=\max(f_{i-1,j},f_{i,j-1},f_{i-1,j-1})+1\ ...
- 【NOIP2016提高A组五校联考4】ksum
题目 分析 发现,当子段[l,r]被取了出来,那么[l-1,r].[l,r+1]一定也被取了出来. 那么,首先将[1,n]放入大顶堆,每次将堆顶的子段[l,r]取出来,因为它是堆顶,所以一定是最大的子 ...
- 【JZOJ4815】【NOIP2016提高A组五校联考4】ksum
题目描述 输入 输出 样例输入 3 4 1 3 4 样例输出 8 7 4 4 数据范围 样例解释 解法 二分做法 考虑到可以二分第k大的值mid,如果比mid大的区间和数小于或等于mid,那么mid就 ...
- 【JZOJ4817】【NOIP2016提高A组五校联考4】square
题目描述 输入 输出 样例输入 3 4 1 1 0 1 0 1 1 0 0 1 1 0 5 1 1 2 3 2 1 3 2 3 2 3 4 1 1 3 4 1 2 3 4 样例输出 1 1 1 2 2 ...
随机推荐
- Python基础数据类型-字典(dict)
Python基础数据类型-字典(dict) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客使用的是Python3.6版本,以及以后分享的每一篇都是Python3.x版本的哟 ...
- CF #442 div2
A 判断下5个名字出现了几次.pre数据巨弱,就这么一水题在std测刷掉了非常多的人.. /** @Date : 2017-10-24 16:04:41 * @FileName: A.cpp * @P ...
- 兼容 IE6+ 获取图片大小
昨天说了 HTML5 的file对象可以获取到文件的 文件名,文件大小,文件类型,最后一次修改日期.其实 IE6-9 也可以变向的获取到,虽然没那么方便,但至少可以取到.来看例子吧: <!doc ...
- CS229 笔记04
CS229 笔记04 Logistic Regression Newton's Method 根据之前的讨论,在Logistic Regression中的一些符号有: \[ \begin{eqnarr ...
- 【CodeForces】925 C.Big Secret 异或
[题目]C.Big Secret [题意]给定数组b,求重排列b数组使其前缀异或和数组a单调递增.\(n \leq 10^5,1 \leq b_i \leq 2^{60}\). [算法]异或 为了拆位 ...
- 第5月第21天 bugly ios证书位置
1.bugly 一. 本地测试 补丁编写规则参见: JSPatch 将补丁文件main.js拖拽到工程内: 开启 BuglyConfig 中的热更新本地调试模式: BuglyConfig *confi ...
- start-stop-daemon 启动停止系统守护进程
1.start-stop-daemon start-stop-daemon是一个Debian体系里的一个守护进程管理软件,可以用指定的用户启停软件.CentOS有自己的daemon()机制(在/etc ...
- fpm制作rpm包
一.前言 在企业中我们有事安装软件包.部分都是源码安装,如nginx安装路径都已经固化了,但实际业务中,我们都是把软件包安装到固定目录下,不满足需要,这是其一.其二,编译安装很耗时,比如mysql,特 ...
- NET 架构指南频道
NET 架构指南频道 微软在Visual Studio 2017 正式发布的时候也上线了一个参考应用https://github.com/dotnet/eShopOnContainers , 最近微软 ...
- 039 DataFrame的理解
1.构成 由RDD+Schema构成 RDD: DataFrame中的数据 ===> df.rdd Schema: RDD中数据的结构 ===> df.schema df是dataFram ...