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;
}
posted @ 2025-11-22 22:45  Yxxxi  阅读(26)  评论(0)    收藏  举报