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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章