[LUOGU]2016 Sam数

我本来想看看SAM,就看见了这个。。
这道题很容易让人想到数位DP,用(f[i][j])表示考虑到第(i)位,最后一位是(j)的方案数。看到1e18,直接矩阵快速幂加速,因为它每位转移都是差不多的。。
(本咸鱼复制的矩阵乘法的板子,结果忘了调矩阵大小,调了半天Orz)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int mod=1000000007;
struct Matrix {
	long long g[11][11];
	int n,m;
	Matrix(){memset(g,0,sizeof g);}
	Matrix operator * (const Matrix &b) const {
		Matrix ans;
		ans.n=n,ans.m=b.m;
		for(int i=0;i<n;i++) 
		for(int j=0;j<b.m;j++)
		for(int k=0;k<m;k++)
		ans.g[i][j]=(ans.g[i][j]+g[i][k]*b.g[k][j])%mod;
		return ans; 
	}
}A,B;
long long n;
Matrix ksm(Matrix d,long long z) {
	Matrix ans;
	ans.n=d.n,ans.m=d.n;
	for(int i=0;i<ans.n;i++)
	ans.g[i][i]=1;
	while(z) {
		if(z&1) ans=ans*d;
		d=d*d;
		z>>=1;
	}
	return ans;
}
int main() {
	A.n=1,A.m=10;
	B.n=10,B.m=10;
	cin>>n;
	if(n==1) {
		puts("10");return 0;
	}
	for(int i=1;i<=9;i++)
	A.g[0][i]=1;
	for(int i=0;i<10;i++)
	for(int j=0;j<10;j++)
	if(abs(i-j)<=2) B.g[i][j]++;
	B=A*ksm(B,n-1);
	long long ans=0;
	for(int i=0;i<10;i++)
	ans=(ans+B.g[0][i])%mod;
	cout<<ans;
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9329376.html