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 << '
' ;
		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 << '
';
}
signed main()
{
	int t=1;
	while(t--)
		solve();
	return 0;
}


原文地址:https://www.cnblogs.com/QingyuYYYYY/p/13621433.html