A 超市里扫货
思路:签到题,模拟一遍即可
#include<iostream>
using namespace std;
int main(){
long long n,v;
cin>>n>>v;
long long num=0,sum=0;
for(int i=0;i<n;i++){
long long x;
cin>>x;
if(sum<=v&&sum+x>v){
num++;
sum=x;
// cout<<x<<endl;
}
else sum+=x;
}
num++;
cout<<num;
}
B 柜台结账
思路:首先确定s2[0]和5的大小,然后如果当前是5然后找一下后面是不是有大与0的数有的话归到大于0.5之列,然后根据题目模拟即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--);
const int N=2e5+7;
int a[N];
int n,m,k;
signed main(){
string a1,a2;
cin>>a1>>a2;
int f=0,_5=0,_big5=0;
n=a2.size();
m=a1.size();
if(a2[0]=='0'){
cout<<"PLMM";
return 0;
}
rep(i,0,n-1){
if(i==0&&a2[i]<'5')break;
if(i==0&&a2[i]=='5')_5=1;
if(i==0&&a2[i]>'5'){
_big5=1;
break;
}
if(a2[i]!='0'&&i>0){
f=1;
break;
}
}
if(f==0&&_5==0&&_big5==0){
cout<<"Happy birthday to YXGG";
}
else if(_big5==1){
cout<<"Happy birthday to MFGG";
}
else if(f==0&&_5==1){
//cout<<"-----"<<endl;
int a=a1[m-1]-'0';
//cout<<a<<endl;
if(a%2==1){
cout<<"Happy birthday to MFGG";
}
else{
cout<<"Happy birthday to YXGG";
}
}
else if(f==1&&_5==1){
cout<<"Happy birthday to MFGG";
}
}
C 小喵觅食
思路:首先是判断通过PLMM 的移动是否能让猫闻到小鱼的味道,如果能闻到通过bfs走一遍即可找到是否能吃到小鱼
#include <stdio.h>
#include <queue>
#include <math.h>
using namespace std;
const int N=1005;
int dist[N][N],n,m,qx,qy,zx,zy,r1,r2;
bool st[N][N];
char a[N][N];//保存地图
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
typedef pair<int,int> PII;
void bfs()//求起点到终点的最短路径
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) dist[i][j]=0x3f3f3f3f;
}
queue<PII> q;
q.push({qx,qy});
dist[qx][qy]=0;
st[qx][qy]=true;
while(q.size())
{
int x=q.front().first;
int y=q.front().second;
q.pop();
for(int i=0;i<4;i++)
{
int x3=x+dx[i];
int y3=y+dy[i];
if(!(x3>=1&&x3<=n&&y3>=1&&y3<=m)) continue;
if(a[x3][y3]=='*') continue;
if(!st[x3][y3])
{
dist[x3][y3]=dist[x][y]+1;
q.push({x3,y3});
st[x3][y3]=true;
}
}
}
}
bool flag;//记录能否让猫闻到
bool st1[N][N];//记录点是否已经走过
void dfs(int x,int y)//遍历人能到的所有点
{
if((abs(x-zx)+abs(zy-y))>r1||flag||st1[x][y]==true) return;
st1[x][y]=true;
for(int i=0;i<4;i++)
{
int x3=x+dx[i];
int y3=y+dy[i];
if(!(x3>=1&&x3<=n&&y3>=1&&y3<=m)) continue;
if(a[x3][y3]=='*'||st1[x3][y3]) continue;
if((abs(x-qx)+abs(qy-y))<=r2)
{
flag=true;
break;
}
dfs(x3,y3);
}
}
void solve()
{
flag=false;
dfs(zx,zy);
if(!flag)//如果人行走范围都无法让猫闻到
{
printf("-1\n");
return;
}
bfs();
if(dist[zx][zy]==0x3f3f3f3f) printf("-1\n");//表示到不了
else printf("%d\n",dist[zx][zy]);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&r1,&r2);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf(" %c",&a[i][j]);
if(a[i][j]=='P') zx=i,zy=j,a[i][j]='.';//记录终点,并变为'.'表示可走
if(a[i][j]=='M') qx=i,qy=j;//记录起点
}
}
solve();
return 0;
}
D 石油大亨
思路:复杂的模拟题。可以使用优先级队列(小根堆)按时间轴顺序模拟事件:培养工程师、占领油田、等待金币上升以再次培养工程师。
#include <iostream>
#include <queue>
#include <set>
#define t first
#define e second
using namespace std;
typedef long long LL;
typedef pair<LL, int> PLI;
const LL eu = 1e12;
const int N = 100010;
LL n, ec, et, p, s;
int t[N];
//事件
//0 --- 钱足够培养一名工程师
//1 --- 刚刚培养了一名工程师
//2 --- 刚刚占领了一块油田
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> ec >> et >> p >> s;
for(int i = 1; i <= n; i++) cin >> t[i];
if(s < ec)
{
cout << "-1" << endl;
return 0;
}
//定义小根堆
priority_queue<PLI, vector<PLI>, greater<PLI>> q;
q.push({0, 0});
//ans 是最终答案,nxt是下一次占领的目标,ls_time是上次循环的时间
//done是已经占领的油田数量
//training是目前有没有在培养工程师
//man是已经培养的工程师数量
LL ans = 0, nxt = 1, done = 0, ls_time = 0, training = 0, man = 0;
while(q.size())
{
auto now = q.top();
q.pop();
//防止金额一直加到溢出long long,因此将s换成足够大的数
s = min(s + min(eu, (now.t - ls_time) * done * p), eu);
//处理当前事件
if(now.e == 1)
{
training = 0;
man++;
}
else if(now.e == 2)
{
done++;
}
//往队列中插入事件2并更新答案
if(nxt <= n && man)
{
PLI tmp = {now.t + t[nxt], 2};
ans = max(ans, now.t + t[nxt]);
q.push(tmp);
nxt++;
man--;
}
//往队列中插入事件1
if(s >= ec && !training)
{
q.push({now.t + et, 1});
s -= ec;
training = 1;
}
//金额不足够培养工程师时,需要一定时间
//等待已经占领的油田产出足够的金额
if(s < ec && done)
{
//上取整
LL need_time = (ec - s) / (done * p) + ((ec - s) % (done * p) != 0);
q.push({now.t + need_time, 0});
}
ls_time = now.t;
if(nxt == n + 1) break;
}
cout << ans << endl;
return 0;
}
E 排队
#include <iostream>
#include <unordered_map>
#define x first
#define y second
using namespace std;
typedef long long LL;
const int N = 100010, mod = 1e9 + 7;
//inv2是1/2在模mod意义下的逆元
const LL inv2 = (mod + 1) / 2;
int n;
int a[N];
int main()
{
unordered_map<int, int> ha;
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
ha[a[i]]++;
}
LL c = (LL)n * (n - 1) / 2;
for(auto t: ha)
{
if(t.y > 1)
{
c -= (LL)t.y * (t.y - 1) / 2;
}
}
c %= mod;
LL fac = 1;
for(int i = 1; i <= n; i++)
{
fac = fac * i % mod;
}
LL res = fac * inv2 % mod * c % mod;
cout << res << endl;
return 0;
}
F 选座椅
#include <iostream>
#include <vector>
using namespace std;
const int N = 100010, mod = 1e9 + 7;
typedef long long LL;
int n, m;
int a[N], b[N], c[N];
//满足第 i 个条件的座椅的数量
//1<=i<=m,表示ai、bi、ci至少一个满足
int cnt[N];
//v[i]是第 i 个座椅满足的条件
vector<int> v[N];
//差分数组和阶乘数组
LL f[N], fac[N];
//将第 idx 个物品加入到当前枚举的区间 [l,r]
void add(int idx, int &now)
{
for(auto t: v[idx])
{
cnt[t]++;
if(cnt[t] == 1) now++;
}
}
//add 的反操作
void del(int idx, int &now)
{
for(auto t: v[idx])
{
cnt[t]--;
if(cnt[t] == 0) now--;
}
}
//计算阶乘
void init()
{
fac[0] = 1;
for(int i = 1; i <= N; i++)
fac[i] = fac[i - 1] * i % mod;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
init();
for(int i = 1; i <= m; i++)
{
cin >> a[i];
v[a[i]].push_back(i);
}
for(int i = 1; i <= m; i++)
{
cin >> b[i];
v[b[i]].push_back(i);
}
for(int i = 1; i <= m; i++)
{
cin >> c[i];
v[c[i]].push_back(i);
}
//now 是符合条件的物品数
int now = 0, r = 1;
for(int l = 1; l <= n; l++)
{
//循环结束后如果now == m
//那么[l, r - 1]表示当前的满足条件的区间
while(now < m && r <= n)
{
add(r, now);
r++;
}
if(now == m)
{
f[(r - 1) - l + 1]++;
f[n - l + 2]--;
}
del(l, now);
}
for(int i = 1; i <= n; i++)
{
f[i] += f[i - 1];
cout << f[i] * fac[i] % mod << ' ';
}
cout << endl;
return 0;
}