hdu 5564 快速矩阵幂+数位dp

hdu5564

这道题一看就知道用数位dp,但是在状态转移时,发现不可能转移成功,10^9,但是发现转移可以用矩阵来进行表示,因此……

但是要注意矩阵最后一列用来计算结果。代码看看就好了,毕竟卡着时间过的,2500ms左右,标程3000ms.

//hdu 5564 快速矩阵幂+数位dp
#include<stdio.h>
#include<cstdlib>
#include<istream>
#define mod 1000000007
#define long long ll
using namespace std;
struct Mat
{
	int on[72][72];
	void init()
	{
		int i, j;
		for (i = 0;i <= 71;i++)
			for (j = 0;j <= 71;j++)
				this->on[i][j] = 0;
	}
	friend Mat operator*(Mat a, Mat b);
	friend Mat operator^(Mat a, int n);
};

Mat operator*(Mat a, Mat b)
{
	Mat res;
	res.init();
	int i, j, l;
	for (i = 0;i <= 70;i++)
		for (j = 0;j <= 70;j++)
			for (l = 0;l <= 70;l++)
			{
		           res.on[i][j] = (res.on[i][j] +(1ll*a.on[i][l]*b.on[l][j])%mod) % mod;
			}
	return res;
}

Mat operator^(Mat a, int n)
{
	Mat b;
	b.init();
	int i;
	for (i = 0;i <= 70;i++)
		b.on[i][i] = 1;
	while (n)
	{
		if (n % 2)
		{
			b = b*a;
		}
		a = a*a;
		n = n / 2;
	}
	return b;
}

int main()
{
	int T;
	//freopen("d:\\in.txt", "r", stdin);
	scanf("%d", &T);
	while (T--)
	{
		int l, r, k;
		scanf("%d%d%d", &l, &r, &k);
		Mat a,b;
		a.init();
		b.init();
		int i,j,t;
		for (i = 1;i <= 9;i++)
			a.on[0][i%7*10+i] = 1;
		for (i = 0;i <= 6;i++)
			for (j = 0;j <= 9;j++)
				for (t = 0;t <= 9;t++)
				{
					if ((j + t) != k)
						b.on[i*10+j][(i*10+t)%7*10+t] = 1;
				}
		for (i = 0;i <= 9;i++)
			b.on[i][70] = 1;
		b.on[70][70] = 1;
		Mat a1, a2;
		a1.init();
		a2.init();
		a1 = a*(b ^ (l - 1));
		a2 = a*(b^r);
		printf("%d\n", (a2.on[0][70] - a1.on[0][70]+mod)%mod);
	}
	return 0;
}

你可能感兴趣的:(hdu 5564 快速矩阵幂+数位dp)