码迷,mamicode.com
首页 > 其他好文 > 详细

Krypton Number System UVA - 11651

时间:2021-06-08 22:43:20      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:emc   矩阵快速幂   base   pac   sign   初始   pre   scan   sys   

原题链接
考察:矩阵快速幂+线性dp
思路:
??这个dp定义完全不敢往那方面想(),定义f[i][j]为分数为i,最后一位为j的方案数.

  1. i==0 f[0][1~base] = 1;
  2. 显然 f[1][j] += f[0][k] j与k的差的平方=1
    以此类推,但是当i>(base-1)*(base-1)时,显然出现了某种规律,详细见这位大佬的博客吧...我是没想到,而且初始化初始的很聪明. GO

??要说的事只有一个:谨慎防止数组越界

Code

#include <iostream>
#include <cstring> 
using namespace std;
typedef long long LL;
const int N = 10,M = 155;
int base,score;
unsigned int dp[M][N],f[M],a[M][M];
void init()
{
	memset(dp,0,sizeof dp);
	memset(a,0,sizeof a);
	memset(f,0,sizeof f);
	for(int i=1;i<base;i++) dp[0][i] = 1;
	for(int i=1;i<(base-1)*(base-1);i++)
	  for(int j=0;j<base;j++)
	   for(int k=0;k<base;k++)
	   {
	   	 int d=  (j-k)*(j-k);
	   	 if(i-d<0||!d) continue;//细节过多 
	   	 dp[i][j]+=dp[i-d][k];
	   }
	for(int i=0;i<(base-1)*(base-1);i++)
	  for(int j=0;j<base;j++)
	    f[i*base+j] = dp[i][j];
	int up = (base-1)*(base-1)*base;
	for(int i=base;i<up;i++)
	  a[i][i-base] = 1;  
	int p = (base-1)*(base-1);
	for(int k=0;k<base;k++)
	  for(int j=0;j<base;j++)
	  {//神优化 的初始化= = 
	    if(k==j) continue;
	  	int d = (k-j)*(k-j);
	  	a[(p-d)*base+j][up-base+k] = 1;
	  }
}
void mul(unsigned int f[],unsigned int a[][M])
{
	unsigned int res[M];
	memset(res,0,sizeof res);
	int Maxn = (base-1)*(base-1)*base;
	for(int i=0;i<Maxn;i++)
	  for(int j=0;j<Maxn;j++)
	    res[i] = (res[i]+(LL)f[j]*a[j][i]);
	memcpy(f,res,sizeof res);
}
void mul(unsigned int a[][M])
{
	unsigned int res[M][M];
	memset(res,0,sizeof res);
	int Maxn = (base-1)*(base-1)*base;
	for(int i=0;i<Maxn;i++)
	  for(int j=0;j<Maxn;j++)
	   for(int k=0;k<Maxn;k++)
	     res[i][j] = (res[i][j]+(LL)a[i][k]*a[k][j]);
	memcpy(a,res,sizeof res);
}
int main()
{
	int T,kcase = 0;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&base,&score);
		init();
		unsigned int ans = 0;
		if(score<(base-1)*(base-1))
		{	
			for(int i=0;i<base;i++)
			  ans+=dp[score][i];
			printf("Case %d: %u\n", ++kcase,ans);
			continue;
		}
		score-=(base-1)*(base-1)-1;
		while(score)
		{
			if(score&1) mul(f,a);
			mul(a);
			score>>=1;
		}
		int up = (base-1)*(base-1)-1;
		for(int i=0;i<base;i++)
		  ans+=f[up*base+i];
		printf("Case %d: %u\n",++kcase,ans);
	}
	return 0;
}

Krypton Number System UVA - 11651

标签:emc   矩阵快速幂   base   pac   sign   初始   pre   scan   sys   

原文地址:https://www.cnblogs.com/newblg/p/14861081.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!