HDU2048?神、上帝以及老天爺
HDU 2006'10 ACM contest的頒獎晚會隆重開始了!
為了活躍氣氛,組織者舉行了一個別開生面、獎品豐厚的抽獎活動,這個活動的具體要求是這樣的:
首先,所有參加晚會的人員都將一張寫有自己名字的字條放入抽獎箱中;
然后,待所有字條加入完畢,每人從箱中取一個字條;
最后,如果取得的字條上寫的就是自己的名字,那么“恭喜你,中獎了!”
大家可以想象一下當時的氣氛之熱烈,畢竟中獎者的獎品是大家夢寐以求的Twins簽名照呀!不過,正如所有試圖設計的喜劇往往以悲劇結尾,這次抽獎活動最后竟然沒有一個人中獎!
我的神、上帝以及老天爺呀,怎么會這樣呢?
不過,先不要激動,現在問題來了,你能計算一下發生這種情況的概率嗎?
不會算?難道你也想以悲劇結尾?!
?Input
輸入數據的第一行是一個整數C,表示測試實例的個數,然后是C 行數據,每行包含一個整數n(1<n<=20),表示參加抽獎的人數。Output
對于每個測試實例,請輸出發生這種情況的百分比,每個實例的輸出占一行, 結果保留兩位小數(四舍五入)
Sample Input
1 2
Sample Output
50.00%
?
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = (int)1e5 + 10;
typedef long long ll;
ll D[25];
int main()
{D[0]=0,D[1]=0,D[2]=1;for(int i=3;i<=20;++i)D[i]=(i-1)*(D[i-1]+D[i-2]);int t;cin>>t;while(t--){int n;cin>>n;double sum=exp(lgamma(n+1));// cout<<sum<<' '<<exp(lgamma(n+1))<<endl;//<<' '<<D[n]<<endl;printf("%.2lf%%\n",D[n]*100.0/sum);}return 0;
}
HDU2047?阿牛的EOF牛肉串
今年的ACM暑期集訓隊一共有18人,分為6支隊伍。其中有一個叫做EOF的隊伍,由04級的阿牛、XC以及05級的COY組成。在共同的集訓生活中,大家建立了深厚的友誼,阿牛準備做點什么來紀念這段激情燃燒的歲月,想了一想,阿牛從家里拿來了一塊上等的牛肉干,準備在上面刻下一個長度為n的只由"E" "O" "F"三種字符組成的字符串(可以只有其中一種或兩種字符,但絕對不能有其他字符),阿牛同時禁止在串中出現O相鄰的情況,他認為,"OO"看起來就像發怒的眼睛,效果不好。
你,NEW ACMer,EOF的崇拜者,能幫阿牛算一下一共有多少種滿足要求的不同的字符串嗎?
PS: 阿牛還有一個小秘密,就是準備把這個刻有 EOF的牛肉干,作為神秘禮物獻給杭電五十周年校慶,可以想象,當校長接過這塊牛肉干的時候該有多高興!這里,請允許我代表杭電的ACMer向阿牛表示感謝!
再次感謝!
Input
輸入數據包含多個測試實例,每個測試實例占一行,由一個整數n組成,(0<n<40)。
Output
對于每個測試實例,請輸出全部的滿足要求的涂法,每個實例的輸出占一行。
Sample Input
1
2
Sample Output
3
8
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = (int)1e5 + 10;
typedef long long ll;
ll f[55];
int main()
{int n;f[1]=3,f[2]=8;//f[3]=22;for(int i=3;i<=40;++i)f[i]=(f[i-1]+f[i-2])*2;while(cin>>n){cout<<f[n]<<endl;}return 0;
}
HDU 2046?
在2×n的一個長方形方格中,用一個1× 2的骨牌鋪滿方格,輸入n ,輸出鋪放方案的總數.
例如n=3時,為2× 3方格,骨牌的鋪放方案有三種,如下圖:
Input
輸入數據由多行組成,每行包含一個整數n,表示該測試實例的長方形方格的規格是2×n (0<n<=50)
Output
對于每個測試實例,請輸出鋪放方案的總數,每個實例的輸出占一行。
Sample Input
1 3 2
Sample Output
1 3 2
不和走樓梯每次走1或者2得一樣嘛
?
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = (int)1e5 + 10;
typedef long long ll;
ll f[10005];
int main()
{int t,n;f[1]=1;f[2]=2;for(int i=3;i<=50;++i)f[i]=f[i-1]+f[i-2];while(cin>>n){cout<<f[n]<<endl;}return 0;
}
HDU 2045?不容易系列之(3)—— LELE的RPG難題
人稱“AC女之殺手”的超級偶像LELE最近忽然玩起了深沉,這可急壞了眾多“Cole”(LELE的粉絲,即"可樂"),經過多方打探,某資深Cole終于知道了原因,原來,LELE最近研究起了著名的RPG難題:
有排成一行的n個方格,用紅(Red)、粉(Pink)、綠(Green)三色涂每個格子,每格涂一色,要求任何相鄰的方格不能同色,且首尾兩格也不同色.求全部的滿足要求的涂法.
以上就是著名的RPG難題.
如果你是Cole,我想你一定會想盡辦法幫助LELE解決這個問題的;如果不是,看在眾多漂亮的痛不欲生的Cole女的面子上,你也不會袖手旁觀吧?
Input
輸入數據包含多個測試實例,每個測試實例占一行,由一個整數N組成,(0<n<=50)。
Output
對于每個測試實例,請輸出全部的滿足要求的涂法,每個實例的輸出占一行。
Sample Input
1
2
Sample Output
3
6
若第n-1個格子和第一個格子不同,則為f(n-1);
若第n-1個格子和第1個格子相同,則第n-2個格子和第一個格子必然不同,此時為f(n-2)再乘第n-1個格子的顏色數,很顯然第n-1個格子可以是第一個格子(即第n-2個格子)的顏色外的另外兩種,這樣為2*f(n-2);
有個坑就是f(3)=3;
?
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = (int)1e5 + 10;
typedef long long ll;
ll f[55];
int main()
{int n;f[1]=3,f[2]=6;f[3]=6;for(int i=4;i<=50;++i)f[i]=f[i-1]+f[i-2]*2;while(cin>>n){cout<<f[n]<<endl;}return 0;
}
HDU2044?一只小蜜蜂...
有一只經過訓練的蜜蜂只能爬向右側相鄰的蜂房,不能反向爬行。請編程計算蜜蜂從蜂房a爬到蜂房b的可能路線數。
其中,蜂房的結構如下所示。
Input
輸入數據的第一行是一個整數N,表示測試實例的個數,然后是N 行數據,每行包含兩個整數a和b(0<a<b<50)。
Output
對于每個測試實例,請輸出蜜蜂從蜂房a爬到蜂房b的可能路線數,每個實例的輸出占一行。
Sample Input
2 1 2 3 6
Sample Output
1 3
半分鐘看題,一分鐘半分鐘出思路
好,果然wa ,抑郁了,
,,,,沒開longlong
?
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = (int)1e5 + 10;
typedef long long ll;
ll f[55];
int main()
{int t,a,b;f[1]=1,f[2]=1;for(int i=3;i<=50;++i)f[i]=f[i-1]+f[i-2];cin>>t;while(t--){cin>>a>>b;cout<<f[b-a+1]<<endl;}return 0;
}
HDU 2041? 超級樓梯
有一樓梯共M級,剛開始時你在第一級,若每次只能跨上一級或二級,要走上第M級,共有多少種走法?
Input
輸入數據首先包含一個整數N,表示測試實例的個數,然后是N行數據,每行包含一個整數M(1<=M<=40),表示樓梯的級數。
Output
對于每個測試實例,請輸出不同走法的數量
Sample Input
2
2
3
Sample Output
1
2
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = (int)1e5 + 10;
typedef long long ll;
ll f[55];
int main()
{f[1]=1,f[2]=1;for(int i=3;i<=40;++i)f[i]=f[i-1]+f[i-2];int t,n;cin>>t;while(t--){cin>>n;cout<<f[n]<<endl;}return 0;
}
HDU2018?母牛的故事
有一頭母牛,它每年年初生一頭小母牛。每頭小母牛從第四個年頭開始,每年年初也生一頭小母牛。請編程實現在第n年的時候,共有多少頭母牛?
Input
輸入數據由多個測試實例組成,每個測試實例占一行,包括一個整數n(0<n<55),n的含義如題目中描述。
n=0表示輸入數據的結束,不做處理。
Output
對于每個測試實例,輸出在第n年的時候母牛的數量。
每個輸出占一行。
Sample Input
2 4 5 0
Sample Output
2 4 6
寫下前6天得母牛的個數 2 3 4 6 9 13 就會知道f(n)=f(n-1)+f(n-3)
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = (int)1e5 + 10;
typedef long long ll;
int f[60];
int main()
{int n;f[1]=1,f[2]=2,f[3]=3;for(int i=4;i<=55;++i)f[i]=f[i-1]+f[i-3];while(cin>>n,n!=0){cout<<f[n]<<endl;}
}
CF687C? ?The Values You Can Mak
??出題
給你一些硬幣,讓你選出一個子集的總價值和為k,然后對于一個選出的子集,除了可以組成k以外,還可以在選出的子集中選出一些其他的價值。問你所有的選出的子集一共可以得到多少種價值。?
看的題解:
這個也可以說是一個01背包了,里面也有一些集合的思想在里面,首先dp方程,dp[i][j]代表著當前數值為i,j能否被構成,如果dp[i][j] = 1,那么dp[i+m][j] 和 dp[i+m][j+m] = 1,所以轉移方程就寫出來了,但是注意我們只能從后向前轉移,
也就是說我們一定要用選上一個數的狀態,因為這里是01背包,每一個數只能選一次,如果正著選就是完全背包了。
還有就是可以作為母函數的入門題
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
int dp[505][505];
int main()
{int n,k,num;cin>>n>>k;memset(dp,0,sizeof(dp));dp[0][0] = 1;for(int p=0;p<n;++p){cin>>num;for(int i = k; i >= num; i--){for(int j = 0; j <= k-num; j++)if(dp[i-num][j])dp[i][j] = dp[i][j+num] = 1;}}int ans = 0;int cnt[555];for(int i = 0; i <= k; i++){if(dp[k][i])cnt[ans++] = i;}cout<<ans<<endl;for(int i=0;i<ans;++i)(i==0?(cout<<cnt[i]):(cout<<' '<<cnt[i]));cout<<endl;return 0;
}
429B?
有一個矩陣,一個人從左上往右下走,一個人從左下往右上走,中間有一次相遇該點的值不算,求最后兩人走過路線值之和的最大值(兩人重復走過的點只計算一次)
記錄矩陣上的每個點分別到矩陣上四個角最大的值,假設某點是相遇點,
該路線的值就是該點到四個角上的最大值之和。因此遍歷矩陣上的每個點,求出最大值即可。
首先要保證只有一個格子重合,那么只可能是以下兩種情況:
1) A向右走,相遇后繼續向右走,而B向上走,相遇后繼續向上走
2) A向下走,相遇后繼續向下走,而B向右走,相遇后繼續向右走
?
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
ll a[1005][1005];
ll dp1[1005][1005];
ll dp2[1005][1005];
ll dp3[1005][1005];
ll dp4[1005][1005];
int main()
{int n,m;while(cin>>n>>m){memset(dp1,0,sizeof(dp1)),memset(dp2,0,sizeof(dp2)),memset(dp3,0,sizeof(dp3)),memset(dp4,0,sizeof(dp4));for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>a[i][j];// 右下for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)dp1[i][j]=max(dp1[i][j-1],dp1[i-1][j])+a[i][j];// 右上for(int i=n;i>=1;--i)for(int j=1;j<=m;++j)dp2[i][j]=max(dp2[i][j-1],dp2[i+1][j])+a[i][j];//左下for(int i=1;i<=n;++i)for(int j=m;j>=1;--j)dp3[i][j]=max(dp3[i][j+1],dp3[i-1][j])+a[i][j];//右上for(int i=n;i>=1;--i)for(int j=m;j>=1;--j)dp4[i][j]=max(dp4[i+1][j],dp4[i][j+1])+a[i][j];ll ans=0;for(int i=2;i<n;++i)//你總不能然他倆在終點和出發點相遇吧for(int j=2;j<m;++j){ans=max(ans,dp1[i-1][j]+dp4[i+1][j]+dp2[i][j-1]+dp3[i][j+1]);ans=max(ans,dp1[i][j-1]+dp4[i][j+1]+dp2[i+1][j]+dp3[i-1][j]);}cout<<ans<<endl;}return 0;
}
?
總結
以上是生活随笔為你收集整理的递推DP的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。