1. 程式人生 > 實用技巧 >9.6 位元組跳動筆試

9.6 位元組跳動筆試

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