2024.11.13 满帮笔试

1.输入两个数n、m,对n进行重新排列,计算重新排列后的数中有多少个可以整除m。

相同的数只能算一次。
1 < = n < = 1 0 15 , 1 < = m < = 100 1<=n<=10^{15},1<=m<=100 1<=n<=1015,1<=m<=100
输入:

322 2

输出:

2

由于n最大不超过16位,用字符串s来进行转换,之后对字符串进行全排列得到每一种能够拼成的数字,用一个集合判断该数字是否重复生成,统计所有能够整除m的个数。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL num,m;
string s;
set<LL> se;
int ans;
int main() {
    cin>>num>>m;
    s=to_string(num);
    sort(s.begin(),s.end());
    do{
        LL t=stoll(s);
        if(!se.count(t)){
            if(t%m==0){
                ans++;
            }
            se.insert(t);
        }
    }while(next_permutation(s.begin(),s.end()));
    cout<<ans;
    return 0;
}

2.n个人,m个房子

每个房子有舒适度和价格,问怎么买房子舒适度总和最大。
确保:
1.每个人最多买一个房子
2.一个房子最多被一个人买
第一行输入n和m,
第二行输入n个人手上有多少钱
后面m行每行为一个房子的舒适度和价格。

2 2
2 2
2 2
2 2
4

贪心思想,用结构体存房子,将价格从小到大排序,舒适度从大到小排序,然后从最小的面额开始匹配,尽可能匹配最大舒适度的情况。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5+10;
int n,m,x,a,b,pos;
struct node{
	int shushi,jiage;
	
	bool operator<(const node&p) const{
		if(jiage!=p.jiage) return jiage<p.jiage;
		return shushi>p.shushi;
	}
};
bool st[N];
vector<node> v;
multiset<int> se;
LL ans;
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		cin>>x;
		se.insert(x);
	}
	for(int i=0;i<m;i++){
		cin>>a>>b;
		v.push_back({a,b});
	}
	sort(v.begin(),v.end());
	
	for(auto x:se){
		for(int i=0;i<v.size();i++){
			if(!st[i] && v[i].jiage<=x){
				ans+=v[i].shushi;
				st[i]=1;
				break;
			}
		}
	}
	cout<<ans;
	return 0;
}

3.给定一个映射:a=1,b=2.…Z=26

请你构造一个数字字符串,恰好有K个只包含小写字母的字符申能映射成这个数字串。
比如K=3,你可以输出"111",因为“aaa”得到数字"111",“ka"或者"ak”也得到是111。
输入一个整数K。输出一个符合要求的数字串。
1 ≤ K ≤ 1 0 18 1≤K≤ 10^{18} 1K1018
要求构造的字符串长度不能超过 1 0 5 10^5 105
答案可能有多种,输出任意一种即可,
如果无法构造,输出-1。
这道题相当于力扣第91题的反问形式:
91. 解码方法

4.有一个n×m的迷宫(左上角是(1,1)),#是石块,.是空地,一个人在S处,出口在F。

但是走出迷宫之前需要按顺序去碰指定的石头,所有石头碰完才能出迷宫。只要在石头上下左右相邻的地点就算碰到。
第一行输入n,m,k(需要碰k块石头)
之后n行输入迷宫
之后k行输入需要碰的石头坐标。
输出离开迷宫的最短时间。
输入

3 5 3
#....
####.
FS...
1 1
2 3
2 2

用bfs找距离当前合法的按石头的距离,然后走到这里,更新当前点Sx,Sy,每一步都是最优距离。

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int n,m,k,a,b,Sx,Sy,Tx,Ty,ans;
char g[N][N];
bool st[N][N];
string s;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
struct node{
    int x,y,d;
    
    bool operator<(const node& other) const {
        if (x != other.x) {
            return x < other.x;
        } else if (y != other.y) {
            return y < other.y;
        } else {
            return d < other.d;
        }
    }
};
int main() {
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        for(int j=1;j<=m;j++)
        {
            g[i][j]=s[j-1];
            if(s[j-1]=='S') Sx=i,Sy=j,g[i][j]='.';
            if(s[j-1]=='F') Tx=i,Ty=j,g[i][j]='.';
        }
    }
    k++;
    while(k--){
        if(k>=1) cin>>a>>b;
        else a=Tx,b=Ty;
        memset(st,0,sizeof(st));
        set<node> se; 	//用一个se来存储当前所有合法的可以按石头的坐标
        for(int i=0;i<4;i++){
            int xx=dx[i]+a,yy=dy[i]+b;
            if(xx>=1 && xx<=n && yy>=1 && yy<=m && g[xx][yy]=='.'){
                se.insert({xx,yy,0});
            }
        }

        queue<node> q;
        q.push({Sx,Sy,0});
        st[Sx][Sy]=1;
        int f=0;
        while(q.size()){
            auto t=q.front(); q.pop();
            for(int i=0;i<4;i++){
                int xx=dx[i]+t.x,yy=dy[i]+t.y;
                if(xx>=1 && xx<=n && yy>=1 && yy<=m && g[xx][yy]=='.' && !st[xx][yy]){
                    q.push({xx,yy,t.d+1});
                    st[xx][yy]=1;
                    for(auto p:se) {
                        if(p.x==xx && p.y==yy){
                            Sx=xx,Sy=yy;
                            ans+=t.d+1;
                            f=1;
                            break;                            
                        }
                    }
                    if(f) break;
                }                
            }
            if(f) break;
        }
        if(!f){ //如果不能按下当前的石头就说明最终无法到达
            cout<<"-1";
            return 0;
        }
        //cout<<ans<<" "<<Sx<<" "<<Sy<<endl;
    }
    cout<<ans;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jay_fearless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值