Day6总结

· 2026-7-16 15:50:39

A.假期

https://qycode64.com/course/6a47850a69fcccaa3fd46be4/exam/6a55f50a47f4ff4971a0c4a3/problem/CF698A?lang=zh 动态规划 题意:在每一天,Vasya 可以选择休息,或者参加比赛(如果这一天有比赛),或者锻炼(如果这一天健身房开放),输出一行,包含一个整数,表示 Vasya 至少需要休息多少天,限制:不能连续两天都锻炼,不能连续两天都参加比赛。 思路:dp[i][j]表示第i天做活动j时,前i天最多能活动多少天,状态转移公式:如果休息(dp[i][0] = max(dp[i-1][0], dp[i-1][1], dp[i-1][2])),如果健身(dp[i][2] = max(dp[i-1][0],dp[i-1][1])+1),如果比赛(dp[i][1] = max(dp[i-1][0], dp[i-1][2]) + 1);

#include<bits/stdc++.h>
using namespace std;
int n,a[105],dp[105][3];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	memset(dp,0x3f,sizeof(dp));
	dp[0][0]=0;
	for(int i=1;i<=n;i++){
		dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]))+1;
		if(a[i]==1||a[i]==3){
			dp[i][1]=min(dp[i-1][0],dp[i-1][2]);
		}
		if(a[i]==2||a[i]==3){
			dp[i][2]=min(dp[i-1][0],dp[i-1][1]);
		}
	}
	cout<<min(dp[n][0],min(dp[n][1],dp[n][2]));
}

B.数字之和

https://qycode64.com/course/6a47850a69fcccaa3fd46be4/exam/6a55f50a47f4ff4971a0c4a3/problem/CF489C?lang=zh

题意:你的任务是找出长度为m,各位数字之和为,s的最小和最大数,若不存在满足条件的数,输出“-1 -1”。 思路:贪心,先特判-1 -1,策略最大数:高位尽可能大,最小数:最高位为1,然后从低位到高位尽可能大。

#include<bits/stdc++.h>
using namespace std;
int main(){
	int m,s,x;
	cin>>m>>s;
	x=s;
	if(s>9*m){
		cout<<"-1 -1";
		return 0;
	}
	if(s==0&&m>1){
		cout<<"-1 -1";
		return 0;
	}
	if(s==0&&m==1){
		cout<<"0 0";
		return 0;
	}
	string a="";
	for(int i=1;i<=9;i++){
		if(i<=x&&x-i<=(m-1)*9){
			a+=char('0'+i);
			x-=i;
			break;
		}
	}
	for(int i=2;i<=m;i++){
		for(int j=0;j<=9;j++){
			if(j<=x&&x-j<=(m-i)*9){
				a+=char('0'+j);
				x-=j;
				break;
			}
		}
	}
	x=s;
	string b="";
	for(int i=1;i<=m;i++){
		for(int j=9;j>=0;j--){
			if(i==1&&j==0&&m>1)continue;
			if(j<=x&&x-j<=(m-i)*9){
				b+=char('0'+j);
				x-=j;
				break;
			}
		}
	}
	cout<<a<<" "<<b;
}

C.美丽序列

https://qycode64.com/course/6a47850a69fcccaa3fd46be4/exam/6a55f50a47f4ff4971a0c4a3/problem/CF1881E?lang=zh

题意:每次操作,你可以删除序列中的任意一个元素。请问最少需要多少次操作才能使给定序列变为美丽序列(定义:如果一个序列可以被分成若干个区块,每个区块的第一个元素表示该区块的长度,接下来是该区块的元素,则称该序列为美丽序列) 思路:我们需要找到最长的美丽子序列,答案=n-最长美丽子序列的长度,dp[i] 表示以位置i作为区块起点时,从i到n能形成的最大美丽序列长度转移:如果选择x作为区块长度,那么这个区块的长度为 x+1,下一个位置从i+x+1开始,公式:如果i+a[i]<=n,dp[i]=a[i]+1+ dp[i+a[i]+1否则:dp[i]=0(无法形成完整区块)要点:倒着用dp

#include<bits/stdc++.h>
	using namespace std;
	int n,a[200005],dp[200005];
	int main(){
		int t;
		cin>>t;
		while(t--){
			cin>>n;
			for(int i=1;i<=n;i++)cin>>a[i];
			for(int i=0;i<=n+1;i++)dp[i]=0;
			for(int i=1;i<=n;i++){
				dp[i]=max(dp[i],dp[i-1]);
				if(i+a[i]<=n){
					dp[i+a[i]]=max(dp[i+a[i]],dp[i-1]+a[i]+1);
				}
			}
			cout<<n-dp[n]<<"\n";
		}
		return 0;
	}

D.小高的生日卡

https://qycode64.com/course/6a47850a69fcccaa3fd46be4/exam/6a55f50a47f4ff4971a0c4a3/problem/CF766C

题意:一条长度为n的信息s,分成若干个非空的子串,不允许英文字母中第i个字母在长度超过ai的字符串中出现,有多少种方法可以将字符串拆分成若干个子串,使得每个子串都满足魔法纸的条件,子串长度之和为n,且互不重叠?请计算方案数对1e9+7取模,在所有合法拆分中,可能出现的最长子串的最大长度是多少?在所有合法拆分方式中,最少需要分成多少个子串? 思路:dp1[i]:前i个字符的分割方案数,状态转移公式:x[i]=sum(dp1[j-1]),初始化x[0]=1,(j到i是合法子串),y[i]:前i个字符最少需要多少个子串,状态转移公式:y[i]=min(y[j-1]+1),(j到i是合法子串),初始化:y[0]=0,最大值:搜索合法子串时找max(···)。

#include<bits/stdc++.h>
	using namespace std;
	int n,a[30],x[1005],y[1005];
	string s;
	int main(){
		cin>>n>>s;
		for(int i=0;i<26;i++)cin>>a[i];
		int ans=0;
		for(int i=0;i<=n;i++)y[i]=1e9;
		x[0]=1;
		y[0]=0;
		for(int i=0;i<n;i++){
			int len=1e9;
			for(int j=i;j<n;j++){
				len=min(len,a[s[j]-'a']);
				if(j-i+1>len)break;
				x[j+1]=(x[j+1]+x[i])%1000000007;
				ans=max(ans,j-i+1);
				y[j+1]=min(y[j+1],y[i]+1);
			}
		}
		cout<<x[n]<<"\n"<<ans<<"\n"<<y[n]<<"\n";
	}

E.棋盘游戏

https://qycode64.com/course/6a47850a69fcccaa3fd46be4/exam/6a55f50a47f4ff4971a0c4a3/problem/CF1033C

题意:游戏棋盘由n个格子组成,排成一行,编号从1到n,每个格子内包含一个1到n之间的数字ai。此外,任意两个格子内的数字都不相同。一个棋子被放在某个格子上。他们轮流移动棋子,Alice 先手。当前玩家可以将棋子从第i个格子移动到第j个格子,要求:aj>ai,|i−j∣mod ai=0,无法进行移动的一方判负,对于每一个可能的初始位置,若双方都采取最优策略,判断谁能获胜,输出一个长度为n的字符串s,其中第i个字符表示若棋子初始放在第i个格子时的游戏结果。如果Alice能获胜,则si等于"A";否则,si等于"B"。 思路:没地方走的地方必败,走到必败地方的地方必胜,走到必胜地方的地方必败,走到必败地方(^o^)/和必胜地方的地方必胜;

#include<bits/stdc++.h>
	using namespace std;
	int n,a[100005],f[100005];
	int dfs(int x){
		if(f[x]!=-1)return f[x];
		int w=0;
		for(int i=a[x];i<=n;i+=a[x]){
			if(x+i<=n&&a[x+i]>a[x]){
				if(dfs(x+i)==0)w=1;
			}
			if(x-i>=1&&a[x-i]>a[x]){
				if(dfs(x-i)==0)w=1;
			}
			if(w)break;
		}
		return f[x]=w;
	}
	int main(){
		cin>>n;
		for(int i=1;i<=n;i++)cin>>a[i];
		memset(f,-1,sizeof(f));
		for(int i=1;i<=n;i++){
			if(dfs(i))cout<<"A";
			else cout<<"B";
		}
	}

F.高雅数

https://qycode64.com/course/6a47850a69fcccaa3fd46be4/exam/6a55f50a47f4ff4971a0c4a3/problem/CF1036C

题意:给定一个区间[L,R],请统计有多少个“高雅数”(它的十进制表示中存在不超过3个的非零数字)整数x满足L≤x≤R 思路:数位DP:dfs(p,c,l) 表示从高位到低位处理到第p位,已经用了c个非零数字,l表示是否贴着上限,统计0到n中非零数字<=3的数字个数。 转移与剪枝:枚举当前位0-9,非零则c+1,若c≤3继续递归,p=0时返回1(所有合法数字都算1个)。 区间答案:sq(n)统计0到n的个数并减去0,最终答案=sq(R)-sq(L-1)。

#include<bits/stdc++.h>
	using namespace std;
	long long f[20][5][2],x,y;
	int t,d[20];
	long long dfs(int p,int c,int l){
		if(!p)return 1;
		if(!l&&f[p][c][l]!=-1)return f[p][c][l];
		long long zx=0;
		int u=9;
		if(l)u=d[p];
		for(int i=0;i<=u;i++){
			int v=c+(i!=0);
			if(v<4)zx+=dfs(p-1,v,l&&i==u);
		}
		if(!l)f[p][c][l]=zx;
		return zx;
	}
	long long sq(long long n){
		if(n<=0)return 0;
		int p=0;
		while(n){
			d[++p]=n%10;
			n/=10;
		}
		memset(f,-1,sizeof(f));
		return dfs(p,0,1)-1;
	}
	int main(){
		cin>>t;
		while(t--){
			cin>>x>>y;
			cout<<sq(y)-sq(x-1)<<"\n";
		}
	}
已修改 6 次查看 举报

0 条评论

目前还没有评论...

Be the first to comment!

返回讨论列表
高士渠
95
通过题目
11
发帖数