LIGHT OJ 1006 - Hex-a-bonacci 【化简递推式(DP)】

1006 - Hex-a-bonacci

Time Limit: 0.5 second(s)Memory Limit: 32 MB

Given a code (not optimized), and necessary inputs, you have to find the output of the code for the inputs. The code is as follows:

int a, b, c, d, e, f;
int fn( int n ) {
    if( n == 0 ) return a;
    if( n == 1 ) return b;
    if( n == 2 ) return c;
    if( n == 3 ) return d;
    if( n == 4 ) return e;
    if( n == 5 ) return f;
    return( fn(n-1) + fn(n-2) + fn(n-3) + fn(n-4) + fn(n-5) + fn(n-6) );
}
int main() {
    int n, caseno = 0, cases;
    scanf("%d", &cases);
    while( cases-- ) {
        scanf("%d %d %d %d %d %d %d", &a, &b, &c, &d, &e, &f, &n);
        printf("Case %d: %d\n", ++caseno, fn(n) % 10000007);
    }
    return 0;
}

Input

Input starts with an integer T (≤ 100), denoting the number of test cases.

Each case contains seven integers, a, b, c, d, e, f and n. All integers will be non-negative and 0 ≤ n ≤ 10000 and the each of the others will be fit into a 32-bit integer.

Output

For each case, print the output of the given code. The given code may have integer overflow problem in the compiler, so be careful.

Sample Input

Output for Sample Input

5

0 1 2 3 4 5 20

3 2 1 5 0 1 9

4 12 9 4 5 6 15

9 8 7 6 5 4 3

3 4 3 2 54 5 4

Case 1: 216339

Case 2: 79

Case 3: 16636

Case 4: 6

Case 5: 54

 

题意:将上述程序优化;

思路:主要就是优化时间复杂度,将递推式化简一下,上面的式子运行最大时间大约10000*10000左右,优化方法 就是用空间换时间,递归换一种方式就是DP思想,两者唯一不同的就是DP的中间状态保存起来了,而递归的中间状态没有被保存起来,导致下一次的查询还要计算中间值,计算了多次中间值,因此只要将中间的状态保存起来,下一次递归是就不用再计算中间值了,所以对上面的程序开一个数组保存中间结果就行了;

失误:比赛时没有想到递归转DP,把公式化简了一下(好麻烦,只是没有耐心推导,推到10项时发现了规律),其实完全是不必要的化简,比赛后再过来看这道题时才发现递归转DP,保存状态优化时间; 另外:数组大小看错,开小了,心里着急一交就错了,以后提交之前先检查一下数组大小,输出输入,数据是否溢出等格式问题,不能在形式上犯错误。


AC代码:

比赛是写的:

#include<cstdio>

typedef long long LL;
const int mod=10000007;

LL a[111111];

int main()
{
	LL T,i,N,Kase=0;
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld %lld %lld %lld %lld %lld %lld",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5],&N);
		a[6]=a[0]+a[1]+a[2]+a[3]+a[4]+a[5];
		for(i=7;i<=N;++i)
		{
			a[i]=(2*a[i-1]%mod-a[i-7]);
			a[i]=(a[i]%mod+mod)%mod;
		}
		printf("Case %lld: %lld\n",++Kase,a[N]%mod);
	}
	return 0;
}


比赛后写的(如果比赛时想到,肯定几分钟解决)

#include<cstdio>

typedef long long LL;
const int mod=10000007;

LL a[111111];

int main()
{
	LL T,i,N,Kase=0;
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld %lld %lld %lld %lld %lld %lld",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5],&N);
		a[6]=a[0]+a[1]+a[2]+a[3]+a[4]+a[5];
		for(i=7;i<=N;++i)
		{
			a[i]=a[i-1]+a[i-2]+a[i-3]+a[i-4]+a[i-5]+a[i-6];
			a[i]=(a[i]%mod+mod)%mod;
		}
		printf("Case %lld: %lld\n",++Kase,a[N]%mod);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值