YL 模拟赛总结 5
Problem
T1
\(m\) 个人中间必定有 \(m-1\) 个空位,剩下 \(n-m+1\) 个位置可以随意放人,则方案数为 \(A^{m}_{n-m+1}\)。
T2
考虑进行 \(dp\)。
状态:令 \(dp_{i,j}\) 表示字符串 \(S_{i \sim j}\) 要变成回文串需要添加的最少字符数。
转移:
枚举区间左端点 \(l\) 和长度 \(k\),右端点为 \(r\)。显然需要进行分类讨论:
若 \(S_l=S_r\),则不需要添加字符,于是 \(dp_{l,r}=dp_{l+1,r-1}\);
否则,可以在 \(l\) 前或 \(r\) 之后添加字符,于是 \(dp_{l,r}=\min(dp_{l+1,r},dp_{l,r-1})+1\)。
#include<bits/stdc++.h> #define int long long using namespace std; string s; int dp[1031][1031]; signed main(){ cin>>s; for(int k=2;k<=s.size();k++){ for(int l=0;l+k-1<s.size();l++){ int r=l+k-1; if(s[l]==s[r]) dp[l][r]=dp[l+1][r-1]; else dp[l][r]=min(dp[l+1][r],dp[l][r-1])+1; } } cout<<dp[0][s.size()-1]; return 0; }
T3
我们可以先写一个 \(\text{brute-force}\),预处理出 \(1 \sim 9\) 位数的各个数位上的数之和的前缀和数组。
然后对于输入的 \(n\),若其数位为 \(s\),则答案为 \(s\) 位数的最小数到 \(n\) 的各个数位上的数之和 \(+ \ sum_{s-1}\),其中 \(sum\) 是我们刚刚求出来的前缀和数组。
但是这样还是会超时。进一步的,若 \(n\) 更靠近 \(s\) 位数的最小数,则使用上述算法,否则答案为 \(sum_s - s\) 位数的最小数到 \(n\) 的各个数位上的数之和 \(+ \ sum_{s-1}\)。
#include<bits/stdc++.h> #define int unsigned long long using namespace std; int n; int t[31]={0,45,900,13500,180000,2250000,27000000,315000000,3600000000,40500000000,1}; //省略快读 int ws(int x){ int res=0; while(x) res++,x/=10; return res; } int f(int x){ int res=0; while(x) res+=x%10,x/=10; return res; } int gz(int x){ int res=0; while(x) res+=pow(10,x-1)*9,x--; return res; } signed main(){ //freopen("count.in","r",stdin); //freopen("count.out","w",stdout); n=read(); int res=0,s=ws(n),w=gz(s); //cout<<gz(s)<<'\n'; if(w-n>n-pow(10,s-1)){ for(int i=pow(10,s-1);i<=n;i++) res+=f(i); write(res+t[s-1]); } else{ for(int i=w;i>n;i--) res+=f(i); write(t[s]-res); } return 0; }
T4
还是考虑 \(dp\)。
状态:令 \(dp_{i,j}\) 表示大小为 \(i\) 行 \(j\) 列的矩阵是否能必胜。
转移:
我们首先需要预处理出 \(pre\) 数组,其中 \(pre_{0,i,j}\) 表示大小为 \(i\) 行 \(j\) 列的矩阵是否可以删除最后一列,\(0\) 表示可以,转移方程:
(\(mp_{i,j}\) 是输入的矩阵)
\(pre_{1,i,j}\) 同理可得。
然后进行 \(dfs\)。
若当前矩阵的最后一列能被删除且删除之后的矩阵未被计算过,则对删去最后一行继续进行 \(dfs\),最后一行同理。
递归返回的时候,若当前矩阵最后一列能被删除,则令 \(a=!dp_{x,y}\)(\(x,y\) 为当前矩阵的规模),最后一行同理,用 \(b\) 记录。
为什么要取反呢?因为递归返回时,若当前矩阵能必胜,则上一层的矩阵是另一个人进行操作,所以不能必胜。必败的情况同理。
最后,将 \(dp_{x,y}\) 设为 \(a \operatorname{or} b\) 即可。
#include<bits/stdc++.h> using namespace std; int t,n,mark; int mp[1031][1031]; int pre[2][1031][1031]; int dp[1031][1031]; bool vis[1031][1031]; void dfs(int x,int y){ vis[x][y]=mark; bool a=0,b=0; if(!x||!y){ dp[x][y]=0; return; } if(!pre[0][x][y]&&vis[x][y-1]!=mark) dfs(x,y-1); if(!pre[1][x][y]&&vis[x-1][y]!=mark) dfs(x-1,y); if(!pre[0][x][y]) a=!dp[x][y-1]; if(!pre[1][x][y]) b=!dp[x-1][y]; dp[x][y]=(a||b); } void solve(){ cin>>n,mark++; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ cin>>mp[i][j]; pre[0][i][j]=(pre[0][i-1][j]+mp[i][j])%2; pre[1][i][j]=(pre[1][i][j-1]+mp[i][j])%2; } dfs(n,n); cout<<(dp[n][n]?"W\n":"L\n"); } int main(){ ios::sync_with_stdio(0); cin>>t; while(t--) solve(); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?