smu模拟赛题解
一:签到(语法基础)
7-1
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
double x;
cin>>n>>x;
cout<<fixed<<setprecision(2)<<n*x*0.1<<'\n';
return 0;
}
7-2
#include<bits/stdc++.h>
using namespace std;
int a[15][15];
int main(){
for(int i=1;i<=10;i++){
for(int j=1;j<=i;j++){
a[1][1]=1;
a[i][1]=1;
a[i][j]=a[i-1][j-1]+a[i-1][j];
}
}
cout<<"杨辉三角形\n";
for(int i=1;i<=10;i++){
for(int j=1;j<=i;j++){
cout<<a[i][j]<<" ";
}
cout<<'\n';
}
return 0;
}
7-3
#include<bits/stdc++.h>
using namespace std;
int a[105];
int f=0,k=0;
void w(int x){
int a=0,b=0,c=0;
a=x/100;
b=(x-a*100)/10;
c=x%10;
if(a*a*a+b*b*b+c*c*c==x){
if(x>=100&&x<=999)cout<<x<<' ';
f=1;
}
}
int main(){
int a,b;
cin>>a>>b;
for(int i=a;i<=b;i++){
w(i);
}
if(f==0)cout<<"No Answer"<<'\n';
else cout<<endl;
return 0;
}
7-4
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int N=105;
const int mod=1e9+7;
int a[N][N],b[N][N],c[N][N];
void solve() {
int r1,c1,r2,c2;
cin>>r1>>c1;
for(int i=0;i<r1;i++){
for(int j=0;j<c1;j++){
cin>>a[i][j];
}
}
cin>>r2>>c2;
for(int i=0;i<r2;i++){
for(int j=0;j<c2;j++){
cin>>b[i][j];
}
}
if(c1!=r2){
cout<<"Error: "<<c1<<" != "<<r2<<endl;
return;
}
for(int i=0;i<r1;i++){
for(int j=0;j<c2;j++){
int sum=0;
for(int k=0;k<c1;k++){
int s=a[i][k]*b[k][j];
sum+=s;
}
c[i][j]=sum;
}
}
cout<<r1<<' '<<c2<<endl;
for(int i=0;i<r1;i++){
for(int j=0;j<c2;j++){
cout<<c[i][j]<<" \n"[j==c2-1];
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}
二:基础算法
7-5:STL(vector/stack)的用法
相性相同:数字相同
性别各异:字母不同
且都为单身:数字不为0
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
int cnt=0,ans=0;
vector<string>ve;
for(int i=0;i<n;i++){
string s;
cin>>s;
if (ve.size()&&ve.back()[0]!='0'&&ve.back()[0]==s[0]&&ve.back()[1]!=s[1]) {
ve.pop_back();
cnt--;
ans++;
} else {
ve.push_back(s);
cnt+=s[0]!='0';
}
cout<<cnt<<endl;
}
cout<<ans<<endl;
return 0;
}
7-6:map && vector用法
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int N=105;
const int mod=1e9+7;
int a[N][N],b[N][N],c[N][N];
void solve() {
int n;cin>>n;
map<string,int>mp;
vector<string>v;
for(int i=0;i<n;i++){
string s;cin>>s;
if(!mp.count(s))v.push_back(s);
mp[s]++;
}
for(int i=0;i<v.size();i++){
cout<<v[i]<<' '<<mp[v[i]]<<'\n';
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
7-7:进制转换 && 找规律 && 枚举 && 映射
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<int>a;
int x=1;
//序列总个数
for(int i=1;i<=n;i++){
x*=26;
}
//计算目标字符串的正数索引x-=m
x-=m;
while(n--){
a.push_back(x%26);// 取当前最低位(0~25)
x/=26;// 去掉最低位,向高位推进
}
//因为是从最低位开始存,所以反转
reverse(a.begin(),a.end());
for(int i=0;i<a.size();i++){
cout<<(char)(a[i]+'a');
// 将26进制位映射为字符
}
return 0;
}
// zzz = 26^3 - 1
// 26^3 - 2
// 26^L - N
// 倒数第1 25 25 25 = 26^3 - 1
// 倒数第2 25 25 24 = 26^3 - 2
// 倒数第n = 26^L - N
// 1 0 0 0
// 26^3
// 1000 = 10^3
// 999 = 10^3 - 1
// 111 = 2^3 - 1
7-8:前缀和 && 二分
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
ll n,m;
cin>>n>>m;
vector <ll> a(n+1); // 存储每天的礼物数量
vector <ll> b(m+1);// 存储每个柜子的容量
vector <ll> s(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++)cin>>b[i];
//要求每个柜子最多可以装多少天的礼物
//所以要从最小的开始装,因此排序
// s[i]是前i个最小礼物的总和
sort(a.begin() + 1, a.begin() + n + 1);
for(int i=1;i<=n;i++){
s[i]=s[i-1]+a[i];
}
// 对每个柜子容量bi,二分查找最大的k
for(int i=1;i<=m;i++){
int l=0,r=n,ans = 0;// ans存储当前柜子能装的最多天数
while(l<=r){
int mid=(l+r)>>1;
if(s[mid]<=b[i]){
// mid 天可行,尝试找更大的天数
ans=mid;
l=mid+1;
}else r=mid-1;
}
cout<<ans;
if(i!=m)cout<<' ';
else cout<<'\n';
}
return 0;
}
7-9:字符串处理
#include<bits/stdc++.h>
using namespace std;
void f(int x) {
//f(x)代表连续6的个数为x
if (x <= 3) {
cout << string(x, '6');
return;
}
if (x <= 9) {
cout << '9';
return;
}
cout << "27";
}
int main(){
string s;
getline(cin,s);
int cnt = 0; // cnt表示连续的6的个数
for(int i=0;i<s.size();i++){
if (s[i] != '6') {
f(cnt);
cnt = 0;
cout << s[i];
} else {
cnt++;
}
}
if (cnt) f(cnt);
// 处理字符串结尾的连续6
// (遍历结束后cnt可能不为0)
return 0;
}
7-10:二分答案
答案具有单调性:如果前 mid 次修改后存在漂亮区间,那么所有 >mid 的时刻一定也存在(因为后续修改只会增加 1 的个数,不会减少);如果前 mid 次修改后不存在,那么所有 <mid 的时刻也一定不存在。
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n,m;
cin>>n>>m;
//cnt1>len/2
vector<pair<int,int>>a(m+1);
for(int i=1;i<=m;i++){
cin>>a[i].first>>a[i].second;
}
int q;
cin>>q;
vector<int>x(q+1);
for(int i=1;i<=q;i++){
cin>>x[i];
}
int L=1,R=q; // 二分的左右边界:时刻范围是 1~q
int ans=-1;
while(L<=R){
int mid=(L+R)/2; //判断前 mid 次修改后是否有漂亮区间
vector<int>b(n+1);
//b[i]=1 表示位置i已被修改为1
vector<int>pre(n+1);
for(int i=1;i<=mid;i++){
b[x[i]]=1;
}
//pre[i]=前i个位置的1的总数(前缀和)
for(int i=1;i<=n;i++){
pre[i]=pre[i-1]+b[i];
}
int f=0;
for(int i=1;i<=m;i++){
auto [l,r]=a[i];
int y1=pre[r]-pre[l-1];//区间内1的个数
int y0=r-l+1-y1;
if(y1>y0){
f=1;
break;
}
}
if(f){//满足漂亮区间
ans=mid;
R=mid-1;// 尝试找更小的时刻
}
else L=mid+1;
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
7-11:搜索 && 联通块
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int r,c,cnt,ans;
vector <string> a;
vector <vector<int> > vis;
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
void dfs(int x,int y, int&f){
if(a[x][y]>'1'&&a[x][y]<='9')f=1;
for(int i=0;i<4;i++){
int tx=x+dx[i],ty=y+dy[i];
if(tx<1||ty<1||tx>r||ty>c||vis[tx][ty]) continue;
if(a[tx][ty]>='1'){
vis[tx][ty]=1;
dfs(tx,ty, f);
}
}
}
int main(){
cin>>r>>c;
// a = vector<string> (r + 1);
a.resize(r + 1);
vis = vector<vector<int> > (r + 1, vector<int>(c + 1));
for(int i=1;i<=r;i++){
cin >> a[i];
a[i] = ' ' + a[i];
}
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
if(a[i][j]!='0' && !vis[i][j]){
// cout << i << ' ' << j << '\n';
int f = 0;
dfs(i,j,f);
cnt++;
if(f)ans++;
}
}
}
cout<<cnt<<' '<<ans<<'\n';
return 0;
}
7-12:dp
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int N=1e5+5;
ll dp[N][5];
void solve(){
ll n,ans=0;
cin>>n;
ans=(dp[n][0] + dp[n][1] + dp[n][2]) %mod;
cout << ans << '\n';
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int t;
cin>>t;
// dp[i][j]表示:
// 长度为i的序列,末尾连续有j只沸羊羊(j=0,1,2)的合法序列数
dp[1][0] = 1; // 序列:L
dp[1][1] = 1; // 序列:F
dp[1][2] = 0; // 长度1无法有连续2个F
// 递推计算n≥2的情况
for (int i = 2; i < N; ++i) {
dp[i][0] = (dp[i-1][0] + dp[i-1][1] + dp[i-1][2]) % mod;
// 序列末尾是L,前 i-1 位可以是任何合法序列
dp[i][1] = dp[i-1][0] % mod;
// j=1:序列末尾是1个F(恰好1个),前i-1位末尾必须是L(j=0,无连续F),否则会变成连续2个及以上F
dp[i][2] = dp[i-1][1] % mod;
// 长度i以FF结尾,前i-1位必须以一个F结尾,追加1只F
}
while(t--){
solve();
}
return 0;
}

浙公网安备 33010602011771号