• 省选模拟赛 Problem 3. count (矩阵快速幂优化DP)


    Discription

    DarrellDarrell 在思考一道计算题。
    给你一个尺寸为 1×N1 × N 的长条,你可以在上面切很多刀,要求竖直地切并且且完后每块的长度都是整数。
    在这种限制下其实只有 N1N − 1 个位置可以切。
    对于一种切的方案,假如切完后每块的宽度分别是:w1,w2,w3,...,wkwi=Nw_1, w_2, w_3, ..., w_k(sum w_i = N),那么该种方案对应
    的完美值为:i=1kwi2 ∏^{k}_{i=1}w_i^2
    那么问题来了,给出 MM 个位置不能切(如果用 xx 表示一个位置,那么切完该位置后长条变为 1×x1 × x
    1×(Nx)1 × (N − x) 两块),那么所有合法切法对应的完美值的和是多少呢?(只需要输出模 109+710^9 + 7 的结果)

    Input

    11 行,有 22 个整数:NMN M,表示长条的总长度及不能切的位置数
    22 行,有 MM 个整数:x1,x2,x3,...,xMx_1, x_2, x_3, ..., x_M 表示不能切的位置。

    Output

    输出 11 行,包含 11 个整数,表示满足要求的所有切法对应的完美值和。(对 109+710^9 + 7 取模后的结果)

    Note

    • 对于 20%20\% 的数据,有 1N,M1031 ≤ N, M ≤ 10^3
    • 对于 60%60\% 的数据,有 1N,M1051 ≤ N, M ≤ 10^5
    • 对于 100%100\% 的数据,有 1N1091M1051 ≤ N ≤ 10^9,1 ≤ M ≤ 10^5,且 1x1<x2<x3<...<xm<N1 ≤ x_1 < x_2 < x_3 < ... < x_m < N


    很显然可以看出DPDP柿子dp[0]=1,   dp[i]=j=0i1dp[j](ij)2dp[0]=1, dp[i]=sum_{j=0}^{i-1}dp[j]*(i-j)^2

    然后答案就为dp[N]dp[N]

    由于NN很大 109le10^9

    所以考虑用矩阵快速幂优化转移

    先想想M=0M=0怎么转移

    定义向量如下:[   j=0idp[j] , j=0idp[j](ij) , j=0idp[j](ij)2   ]left[ sum_{j=0}^idp[j] , sum_{j=0}^idp[j]*(i-j) , sum_{j=0}^idp[j]*(i-j)^2 ight]

    然后考虑从[   j=0i1dp[j] , j=0i1dp[j](i1j) , j=0i1dp[j](i1j)2   ]left[ sum_{j=0}^{i-1}dp[j] , sum_{j=0}^{i-1}dp[j]*(i-1-j) , sum_{j=0}^{i-1}dp[j]*(i-1-j)^2 ight]转移到[   j=0idp[j] , j=0idp[j](ij) , j=0idp[j](ij)2   ]left[ sum_{j=0}^idp[j] , sum_{j=0}^idp[j]*(i-j) , sum_{j=0}^idp[j]*(i-j)^2 ight]

    转移矩阵就是
    [221110121][j=0i1dp[j]j=0i1dp[j](i1j)j=0i1dp[j](i1j)2]=[j=0idp[j]j=0idp[j](ij)j=0idp[j](ij)2]left[egin{matrix} 2&2&1\ 1&1&0\ 1&2&1\ end{matrix} ight] left[egin{matrix} sum_{j=0}^{i-1}dp[j]\ sum_{j=0}^{i-1}dp[j]*(i-1-j)\ sum_{j=0}^{i-1}dp[j]*(i-1-j)^2\ end{matrix} ight] =left[egin{matrix} sum_{j=0}^{i}dp[j]\ sum_{j=0}^{i}dp[j]*(i-j)\ sum_{j=0}^{i}dp[j]*(i-j)^2\ end{matrix} ight] 自己推一推吧…

    注意第二项和第三项当j=ij=i时贡献的值是00因为ij=0i-j=0,所以jj的范围实质上是[0,i1][0,i-1].为了统一就写成[0,i][0,i]了.

    考虑这个地方不能切,我们就强制把这个位置的dpdp值设为00就行了.

    那么不能切的地方的转移,就只用把第一项累加dp[i]dp[i]的系数去掉就行了.第一行也就变成了[2,2,1][1,2,1]=[1,0,0][2,2,1]-[1,2,1]=[1,0,0],那么不能切的地方的转移矩阵就如下:
    [100110121]left[egin{matrix} 1&0&0\ 1&1&0\ 1&2&1\ end{matrix} ight]

    详细见代码

    CODE

    #include<bits/stdc++.h>
    using namespace std;
    inline void read(int &num) {
    	char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg = -flg;
    	for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar()); num*=flg;
    }
    const int MAXN = 1e5+5;
    const int mod = 1e9+7;
    struct mat {
    	int a[3][3];
    	mat() { memset(a,0,sizeof a); }
    	inline void init1() {
    		a[0][0] = 2; a[0][1] = 2; a[0][2] = 1;
    		a[1][0] = 1; a[1][1] = 1; a[1][2] = 0;
    		a[2][0] = 1; a[2][1] = 2; a[2][2] = 1;
    	}
    	inline void init2() {
    		a[0][0] = 1; a[0][1] = 0; a[0][2] = 0;
    		a[1][0] = 1; a[1][1] = 1; a[1][2] = 0;
    		a[2][0] = 1; a[2][1] = 2; a[2][2] = 1;
    	}
    	inline mat operator *(const mat &o)const {
    		mat re;
    		for(int k = 0; k < 3; ++k)
    			for(int i = 0; i < 3; ++i) if(a[i][k])
    				for(int j = 0; j < 3; ++j) if(o.a[k][j])
    					re.a[i][j] = (re.a[i][j] + 1ll * a[i][k] * o.a[k][j] % mod) % mod;
    		return re;
    	}
    	inline mat operator ^(int b)const {
    		mat A = *this, re;
    		re.a[0][0] = re.a[1][1] = re.a[2][2] = 1;
    		while(b) {
    			if(b & 1) re = re * A;
    			A = A * A; b >>= 1;
    		}
    		return re;
    	}
    }ans, trans1, trans2;
    int N, M, pos[MAXN];
    int main() {
    	freopen("count.in", "r", stdin);
    	freopen("count.out", "w", stdout);
    	scanf("%d%d", &N, &M);
    	for(int i = 1; i <= M; ++i)
    		scanf("%d", &pos[i]);
    	ans.a[0][0] = 1;
    	trans1.init1();
    	trans2.init2();
    	for(int i = 1; i <= M; ++i)
    		ans = (trans1^(pos[i]-pos[i-1]-1)) * ans, ans = trans2 * ans;
    	ans = (trans1^(N-pos[M])) * ans;
    	printf("%d
    ", ans.a[2][0]);
    }
    

    妈妈我终于会矩阵快速幂了!!!

  • 相关阅读:
    session笔记-韩顺平
    带宽
    cookie-韩顺平
    分层模式开发+MVC模式开发--韩顺平雇员数据库管理
    韩顺平-雇员管理系统-学习小结
    常用的PHP数据库操作方法(MYSQL版)
    使用Three.js 基本组件以及流程
    three.js 相机
    多线程的操作与数据绑定
    矩阵-
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039286.html
Copyright © 2020-2023  润新知