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