「ZJOI2011」细胞 矩阵快速幂

题意:

输入:

包含两行,其中:

第一行为一个正整数\(n\),表示细胞密码的长度。

第二行共\(n\)个数字,为给定的细胞密码,中间没有空格。

输出:

只包含一个整数,为细胞的种数 \(mod 1000000007\)的结果

思路:

对于第一次分裂,如果切的方法不同,那么分裂出来的球体是不同的,因此不必考虑切出来相同的情况对第二次分裂的结果产生影响。

不同是指:

1、分裂出来的小球个数不同

2、个数相同但质量分布不同

证明的话,可以考虑将一段细胞上的密码用\(abcd\)等代替进行分割,用反证法之类的可以证明

实际上考试的时候可以大胆猜测感性证明×

对于第二次分裂及变异的问题可以转化为,有\(x\)个球,\(x-1\)个丝状物,从中选出一些退化满足相邻的必须有至少一个退化。可以定义出\(dp\)状态,\(dp[i][0]\)表示第\(i\)个不退化,\(dp[i][1]\)则表示退化,那么就能得到两条式子:

dp[i][0]=dp[i-1][1]
dp[i][1]=dp[i-1][0]+dp[i-1][1]

上面这条式子其实是斐波那契数列,问题就转化成了求斐波那契数列第\(x-1\)位,快速求斐波那契数列有矩阵快速幂的写法。

对于第二问就可以选择枚举当前切割的位置为\(i\),上一次的位置为\(j\)\(ans[i]=\sum_{j=1}^{i-1}\,ans[j]*val[j+1][i]\)

但是\(val[j+1][i]\)会很大,写高精也会出现问题,那我们可以换个思路,设矩阵为\(k\)

对于\(i-j\)区间内的贡献为\(k^{val[i][j]}\),将式子再进行转换有\(k^{val[i][j]}=(k^{val[i][j-1]})^{10}*k^{s[j]-'0'}\)

这样子递推过来,我们每次只用再乘上最后一位,所以可以用上述的式子预处理出来\(val[i][j]\)

代码:

#include<bits/stdc++.h>
#define M 1005
#define ll long long
#define Mod 1000000007
using namespace std;
int n;
char s[M];
struct P2 {
	struct node {
		ll a[2][2];
		node() {
			memset(a,0,sizeof(a));
		}
		node operator*(const node&_)const {
			node res;
			for(int i=0; i<2; i++)
				for(int j=0; j<2; j++)
					for(int k=0; k<2; k++)
						res.a[i][k]=(res.a[i][k]+a[i][j]*_.a[j][k]%Mod)%Mod;
			return res;
		}
		void operator+=(const node&_) {
			for(int i=0; i<2; i++)
				for(int j=0; j<2; j++)
					a[i][j]=(a[i][j]+_.a[i][j])%Mod;
		}
	} val[1005][1005],dp[1005],w;
	node mul(node a,int y) {
		node res;
		res.a[0][0]=res.a[1][1]=1;
		while(y) {
			if(y&1)res=res*a;
			a=a*a,y>>=1;
		}
		return res;
	}
	void solve() {
		w.a[0][0]=0,w.a[0][1]=1,w.a[1][0]=1,w.a[1][1]=1;//初始化矩阵
		for(int i=1; i<=n; i++) {
			val[i][i]=mul(w,s[i]-'0');
			for(int j=i+1; j<=n; j++)
				val[i][j]=mul(val[i][j-1],10)*mul(w,s[j]-'0');
		}
		for(int i=1; i<=n; i++) {
			dp[i]=val[1][i];
			for(int j=1; j<i; j++)
				dp[i]+=dp[j]*val[j+1][i];
		}
		printf("%lld\n",dp[n].a[0][0]);
	}
} p2;
int main() {
	scanf("%d%s",&n,s+1);
	p2.solve();
	return 0;
}
posted @ 2019-08-15 08:48  季芊月  阅读(176)  评论(0编辑  收藏  举报