URAL 递推


http://acm.timus.ru/problem.aspx?space=1&num=1225

f[n] = f[n-1] + f[n-2]。

#include <stdio.h>
#include <string.h>
#define LL __int64

int main()
{
	LL f[50];
	f[1] = 2;
	f[2] = 2;

	for(int i = 3; i <= 45; i++)
		f[i] = f[i-1] + f[i-2];
	int x;
	while(~scanf("%d",&x))
	{
		printf("%I64d\n",f[x]);
	}
	return 0;
}


http://acm.timus.ru/problem.aspx?space=1&num=1260

说有n个人,他们的年龄是1~n,拍照时要求年龄为1的在最左边,以后的每个人他与两边的人的年龄差绝对值不超过2.问有多少种排列方法。

推了好久公式。当 n等于 1,2,3,4,5,6时,分别是1,1,2,4,6,9种。

打表找规律吧。先打出前18个。

#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL __int64
#define eps 1e-12
#define PI acos(-1.0)
#define PP pair<LL,LL>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
const int mod = 1000000007;

int cnt;
LL vis[1010];
int mark[20];

void dfs(int cur, LL sum, int pre,int n)
{
	if(cur == n)
	{
		int i;
		for(i = 1; i <= cnt; i++)
			if(vis[i] == sum)
				break;
		if(i > cnt)
			vis[++cnt] = sum;
		return;
	}
	for(int i = 2; i <= n; i++)
	{
		if(!mark[i] && abs(i-pre) <= 2)
		{
			mark[i] = 1;
			dfs(cur+1,sum*10+i,i,n);
			mark[i] = 0;
		}
	}
}

int main()
{
	for(int i = 1; i <= 18; i++)
	{
		cnt = 0;
		if(i == 1)
		{
			printf("%d %d\n",i,1);
			continue;
		}
		memset(mark,0,sizeof(mark));
		dfs(1,1,1,i);
		printf("%d %d\n",i,cnt);
	}
	return 0;
}

发现规律:f[i] = f[i-1] + f[i-3] + 1

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int main()
{
	int n;
	int f[60];

	f[1] = 1;
	f[2] = 1;
	f[3] = 2;
	f[4] = 4;

	for(int i = 5; i <= 55; i++)
	{
		f[i] = f[i-1] + f[i-3] + 1;
	}

	while(~scanf("%d",&n))
	{
		printf("%d\n",f[n]);
	}
	return 0;
}


http://acm.timus.ru/problem.aspx?space=1&num=1009

给出 n和k,n+k <= 18 . 求出k进制数长度为n的数并且不含两个以上连续0的个数。不能有前导零,当n等于1时,只能去1~k-1。


设dp[i][0]和dp[i][1]分别表示到第i位为止,第i位为0第i位不为0的数的个数。那么dp[i][0] = dp[i-1][1],dp[i][1] = (dp[i-1][0] + dp[i-1][1])*(k-1)。


#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL __int64
#define eps 1e-12
#define PI acos(-1.0)
#define PP pair<LL,LL>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
const int mod = 1000000007;

int main()
{
	LL dp[20][2];
	int n,k;
	while(~scanf("%d %d",&n,&k))
	{
		dp[1][0] = 0;
		dp[1][1] = k-1;
		for(int i = 2; i <= n; i++)
		{
			dp[i][0] = dp[i-1][1];
			dp[i][1] = (dp[i-1][1] + dp[i-1][0])*(k-1);
		}
		printf("%I64d\n",dp[n][0] + dp[n][1]);
	}
	return 0;
}




http://acm.timus.ru/problem.aspx?space=1&num=1012

与上题一样,不过这里 n+k <= 180,由于n较大,需要大数加法。再次使用java。发现大数的题目java比较好弄。为了比赛,要多刷几道大数的题目。

import java.io.*;
import java.util.*;
import java.math.*;
import java.math.BigInteger;
public class Main
{
	public static void main(String[] args)
	{
		Scanner cin  = new Scanner (System.in);
		while(cin.hasNext())
		{
			int n = cin.nextInt();
			int k = cin.nextInt();
			BigInteger [] f = new BigInteger [180];
			f[1] = BigInteger.valueOf(k-1);
			f[2] = BigInteger.valueOf(k*(k-1));
			for(int i = 3; i <= n; i++)
			{
				f[i] = f[i-1].add(f[i-2]);
				f[i] = f[i].multiply(BigInteger.valueOf(k-1));
			}
			System.out.println(f[n]);
		}
		
	}
}


你可能感兴趣的:(递推)