9.6 位元組跳動筆試
阿新 • • 發佈:2020-09-06
t1
大概題意
有個樓梯比較高,問有多少種可以方式可以走上去,但有特殊得要求:一是每次可以走一步或者兩步,二是不能連續的走兩步
計算有多少種方法到達頂層
輸入:樓層的層數
輸出:一共有多少種走法
思路:直接dp就好了,設dp方程為dp[i][2],dp[i][0]表示走一步之後達到第i層,那麼轉移方程就是dp[i][0]+=dp[i-1][0]+dp[i-1][1]
dp[i][1]表示走兩步之後達到第i層,那麼轉移方程就是dp[i][1]+=dp[i-2][0];
答案就是到達第n層的兩種狀態dp[n][0]+dp[n][1]
#include<map> #include<queue> #include<time.h> #include<limits.h> #include<cmath> #include<ostream> #include<iterator> #include<set> #include<stack> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep_1(i,m,n) for(int i=m;i<=n;i++) #define mem(st) memset(st,0,sizeof st) inline int read() { int num=0, w=0; char ch=0; while (!isdigit(ch)) { w|=ch=='-'; ch = getchar(); } while (isdigit(ch)) { num = (num<<3) + (num<<1) + (ch^48); ch = getchar(); } return w? -num: num; } typedef long long ll; typedef pair<int,int> pii; typedef unsigned long long ull; typedef pair<double,double> pdd; const int inf = 0x3f3f3f3f; const int N=2e6+10; #define int long long int dp[110][2]; void solve() { int n; cin>>n; dp[1][0]=1; dp[1][1]=0; dp[2][1]=1; dp[2][0]=1; for(int i=3;i<=n;i++) { dp[i][0]+=dp[i-1][0]+dp[i-1][1]; dp[i][1]+=dp[i-2][0]; } cout<<dp[n][0]+dp[n][1]<<endl; } signed main() { int t=1; while(t--) solve(); return 0; }
t3
題目大意
給定一個長度為n的整數序列S,然後把序列複製成m份,也就是變成了n*m的序列,然後在這個新的序列中選取一段連續的整數,使得和最大。
和最大是多少?注意:序列中有負數或者0,至少選一個數,不能不選
思路:首先如果m等於1時,此時此時就是在長度為n的數組裡面選最大的連續欄位和,我們可以用dp來做
當m等於2的時候,也就是直接把陣列複製一遍接到後面,然後dp,n的範圍很小,dp完全足夠
然後當m>2的時候,就是我們找到最大子串之後,還要列舉我們的答案裡面要有幾個這樣的最大字串,當有兩個的時候,也就是可以看作一個最大字串+一個整串,然後列舉個數就好
需要注意的時,此題至少選一個,那麼我們可以把ans設定為0,如果最大字串比0小的話,說明都是負數,我們就可以直接輸出一個最大的負數就好了
具體看程式碼
#include<map> #include<queue> #include<time.h> #include<limits.h> #include<cmath> #include<ostream> #include<iterator> #include<set> #include<stack> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep_1(i,m,n) for(int i=m;i<=n;i++) #define mem(st) memset(st,0,sizeof st) inline int read() { int num=0, w=0; char ch=0; while (!isdigit(ch)) { w|=ch=='-'; ch = getchar(); } while (isdigit(ch)) { num = (num<<3) + (num<<1) + (ch^48); ch = getchar(); } return w? -num: num; } typedef long long ll; typedef pair<int,int> pii; typedef unsigned long long ull; typedef pair<double,double> pdd; const int inf = 0x3f3f3f3f; const int N = 1e6 + 10; #define int long long int a[N] , dp[N]; void solve() { int n , m , sum = 0 , ma = 0 , ans = 0; cin >> n >> m ; //直接賦值,拼成兩段 for(int i=1; i<=n; i++) cin >> a[i] , a[i + n] = a[i] , sum += a[i]; //先求一邊最大子序列的和 for(int i=1; i<=2*n; i++) dp[i] = max(max(dp[i - 1] + a[i] , 0ll) , a[i]); for(int i=1; i<=n; i++) ans = max(ans , dp[i]); //如果只是一次 if(m == 1) { //ans是0,說明都比0小 ,說明都是負數 if(!ans) { //找到最大的那個負數 ans = -0x3f3f3f3f3f3f3fll; for(int i=1; i<=n; i++) ans = max(ans , a[i]); } cout << ans << '\n' ; return ; } //如果m不是1,那麼,就找最大的子段 for(int i=1; i<=2*n; i++) ma = max(ma , dp[i]); //列舉中間有幾個連續的整段 for(int i=2; i<=m; i++) ans = max(ans , sum * (i - 2) + ma); //如果是0的話,說明都是負數 if(!ans) { //就直接找一個最大的負數輸出 ans = -0x3f3f3f3f3f3f3fll; for(int i=1; i<=n; i++) ans = max(ans , a[i]); } cout << ans << '\n'; } signed main() { int t=1; while(t--) solve(); return 0; }