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; }
#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; }
与上题一样,不过这里 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]); } } }