https://ac.nowcoder.com/acm/contest/5678
A、拯救咕咕咕之史莱姆
链接:https://ac.nowcoder.com/acm/contest/5678/A
来源:牛客网
信鸽王国有一位美丽的公主,被可恶的巫师囚禁在了城堡里,你是一位倾慕公主的勇者,准备去解救她。你来到了城堡外,发现有一只丑陋的史莱姆阻挡了你的去路,向你索要进堡费,你囊中羞涩,并不想给钱,于是你给它撒了“洞洞索命粉末”!
洞洞索命粉末:被撒此粉末它的身上就会出现一个大洞,从中毒的第二天开始,大洞每天早上会分裂出一个小洞,小洞在出现后的第四天会长成大洞(并开始分裂),每个洞在每天下午会减少它 3 点 HP,HP 为 0 时它就会死去。史莱姆很聪明,如果他意识到自己第二天就会死去,他就会向你求饶,让开道路。
PS:你从小道消息得知公主就快要饿死了,所以你要赶在 5 天之内进入城堡,如果 5 天之后史莱姆还没有向你求饶,那你只能氪金了。
输入描述:
测试输入包含若干测试用例,每个测试用例占一行,包含一个整数 n(long long范围内),表示史莱姆的初始 HP 值,当 n 为 0 时输入结束。
输出描述:
对每个测试用例,如果 5 天之内(包括第 5 天)史莱姆向你求饶,那就输出“AOLIGEI!”,否则,输出“DAAAAAMN!”,没有双引号。
示例1
输入
复制 5 73 77 0
5 73 77 0
输出
复制 AOLIGEI! AOLIGEI! DAAAAAMN!
AOLIGEI! AOLIGEI! DAAAAAMN!
思路:类似生兔子的dp,不过方便点的无脑方法就是观察样例一个个试过去。在73-77中挑一个数。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5;
typedef long long LL;
LL dp[maxn];
int main(void)
{
LL n;
while(cin>>n&&n!=0)
{
//LL sum=18;
if(n<=75) cout<<"AOLIGEI!"<<endl;
else cout<<"DAAAAAMN!"<<endl;
}
return 0;
}
E-无敌阿姨
链接:https://ac.nowcoder.com/acm/contest/5678/E
来源:牛客网
X 学校最近计划安排宿管阿姨帮每个宿舍的人晒被子,为了提高效率雇佣了一个无敌阿姨,已知无敌阿姨晒被子的方式如下:
1、进入当前有被子的最低层拿尽可能多的被子,每拿走 1 床被子体力值减 1;
2、如果当前层的被子被拿完且此时的体力值大于 k ,消耗 k 点体力值进入到上层楼;
3、在当前层拿尽可能多的被子,每拿走 1 床被子体力值减 1 ,重复步骤 2;
4、如果体力耗尽或者此时的体力小于等于 k ,将被子拿出去放到晾衣架,体力恢复为初始体力值;
PS:阿姨在没有取得被子之前上楼不消耗体力。
先给出楼的层数 n ,阿姨的体力值 m ,阿姨抱着被子上楼的体力消耗值 k ,每层的被子数 aia_iai ,问阿姨需要几次能够把所有被子拿出去?
输入描述:
输入包含多组数据,第一行包含一个数字 T(1≤T≤10)T(1 \le T \le 10)T(1≤T≤10),表示测试数据组数。接下来是T组数据, 每组数据第一行为三个整数 n,m,k(1≤n,m,k≤100)n,m,k(1 \le n,m,k \le 100)n,m,k(1≤n,m,k≤100)分别表示楼的层数,阿姨的体力值以及抱着被子上楼的体力消耗值。 第二行 n 个整数 a1,a2,a3,...,an(1≤ai≤100)a_1,a_2,a_3,...,a_n(1 \le a_i \le 100)a1,a2,a3,...,an(1≤ai≤100) 表示每层的被子数。
输出描述:
每组数据输出包含一个整数,表示阿姨把所有的被子都拿出去需要的次数。
示例1
输入
复制 1 4 5 1 1 1 2 4
1 4 5 1 1 1 2 4
输出
复制 3
3
说明
第一次阿姨先从第一层拿一床被子,再上到第二层拿1床被子,再上到第三层拿一床被子,其中拿被子消耗体力为3,上楼消耗体力为2;第二次阿姨先从第三层拿一床被子,再上到第四层拿三床被子,其中拿被子消耗体力为4,上楼消耗体力为1;第三次阿姨直接从第四层拿一床被子消耗体力为1,全部为拿被子消耗的体力。
思路:模拟的思路一直比较弱,需要借助一些方法来模拟,比如双指针,这里我借助了双端队列模拟。在某场cfdiv4中我看到一个鸽鸽二道或者三道都是deque模拟的。deque用来做模拟题应该会比较方便
#include<iostream>
#include<vector>
#include<queue>
#include<deque>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5;
typedef long long LL;
int main(void)
{
LL t;cin>>t;
while(t--)
{
LL n,m,k;cin>>n>>m>>k;
LL res=0;deque<LL> a;
for(LL i=0;i<n;i++) { LL x;cin>>x;a.push_back(x);}
LL p=m;
LL floor=0;
while(a.size()>0&&a.size()<=n)
{
// cout<<"a.size()="<<a.size()<<endl;
LL t=a[0];
a[0]=a[0]-p;
p-=t;
if(a[0]<=0) a.pop_front(),floor++;
if(p<k||floor==n) res++,p=m;
else if(p>=k) p-=k;
// cout<<"res="<<res<<endl;
}
cout<<res<<endl;
}
return 0;
}
G-校车
链接:https://ac.nowcoder.com/acm/contest/5678/G
来源:牛客网
西安邮电大学有一辆从老校区到新校区的校车,总共有 n 个学生乘坐校车,在 aia_{i}ai 站上车,在 bib_{i}bi 站下车。学校打算去除一部分不必要的站点,请问需要保留多少站点,需要安排多少个座位?
输入描述:
输入 T 组数据 (1≤T≤10)(1 \le T \le 10)(1≤T≤10) 输入 n(1≤n≤105)n(1 \le n \le 10^{5})n(1≤n≤105) 输入 n 组 ai,bi(1≤ai,bi≤109)a_{i},b_{i}(1 \le a_{i},b_{i} \le 10^{9})ai,bi(1≤ai,bi≤109)
输出描述:
输出保留站点数,座位数。
示例1
输入
复制 1 3 1 2 1 3 2 4
1 3 1 2 1 3 2 4
输出
复制 4 2
4 2
思路:对一段数轴进行差分,需要的座位是累加差分的最大值,统计有多少个不重站点就是答案。学生的人数比站点的范围少很多,要离散化。
离散化板子:为了方便debug以后把离散化的板子里面的二分改成STL的
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 3e5+10;
LL n, m;
LL a[maxn], b[maxn],c[maxn];
vector<LL> v;
LL find(LL x)
{
return lower_bound(v.begin(),v.end(),x)-v.begin();
}
int main(void)
{
LL t;cin>>t;
while(t--)
{
v.clear();//多组清空
LL n;cin>>n;
for(LL i=1;i<=n+10;i++) a[i]=b[i]=0;
for(LL i=0;i<n;i++)
{
cin>>a[i]>>b[i];
v.push_back(a[i]);v.push_back(b[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(LL i=0;i<v.size();i++) c[i]=0;
for(LL i=0;i<n;i++)
{
c[find(a[i])]++;
c[find(b[i])]--;
}
LL cnt=c[0], res=cnt;
for(LL i=1;i<v.size();i++)
{
cnt+=c[i];
res=max(res,cnt);
}
cout<<v.size()<<' '<<res<<endl;
}
return 0;
}
H-中位因数
链接:https://ac.nowcoder.com/acm/contest/5678/H
来源:牛客网
题目描述
给出函数的定义如下:
f(x)是所有能够整除 x 的数(包含 1 和 x )中的中位数向下取整的大小,
g(x)=∑i=1xf(i)g(x)=\sum_{i = 1}^{x}{f(i)}g(x)=∑i=1xf(i)
输入描述:
输入包含多组数据,第一行为一个数字 T(1≤T≤10)T(1 \le T \le 10)T(1≤T≤10) ,表示测试数据组数。 接下来是 T 组数据,每组数据为一行,包含一个整数 x(1≤x≤1000000)x(1 \le x \le1000000)x(1≤x≤1000000)
输出描述:
每组数据输出包含一个整数,表示 g(x) 的值,结果要求对 1e9+7 取模。
示例1
输入
复制 3 1 2 3
3 1 2 3
输出
复制 1 2 4
1 2 4
说明
能够整除 1 的数字有 1 ,故 f(1)=1; 能够整除 2 的数字有 1,2 所以中位数为⌊1+22⌋=1\lfloor \frac{1+2}{2} \rfloor = 1⌊21+2⌋=1,故 f(2) = 1; 能够整除 3 的数字有 1,3 ,所以中位数为1+32=2\frac{1+3}{2}=221+3=2 ,故 f(3) = 2; 从而得出 g(1) = 1,g(2) = 2,g(3) = 4 。
示例2
输入
复制 1 1000000
1 1000000
输出
复制 677045223
677045223
思路:对一个数n来说,他的因子会在根号n两侧,那么根号n左边有多少个,根号n右边就有多少个。那么题目的中位因数的意思是让我们找最靠近根号n的两个。(当然可能==根号n的情况)
那么我们进行枚举,假设一个数为x,它会有很多因子,比如有一组配对因子是i,j(我们假设i<=j).
那么先令a[x]=(i+j)/2,使(i+j)/2是x的中位因数,之后不断更新,更新到最后a[x]里面存的是i和j最接近的一对因数的中位因数。
当时没搞懂这个循环,记录一下:类似桶,a[i*j==x],x的因数有i,j,且默认i<=j,然后枚举更新x的中位因数
比如16,刚开始a[16==1*16]=8;到后面会更新到a[16==4*4]==4;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5,mod=1e9+7,M=1e6;
int ans[N],a[N],n,t;
int main(){
memset(a,0x7f,sizeof(a));
for(int i=1;i<=1000;i++)
for(int j=i;i*j<=M;j++)
{
{
a[i*j]=min(a[i*j],(i+j)/2);//类似桶,a[i*j==x],x的因数有i,j,且默认i<=j,然后枚举更新x的中位因数
}
}
for(int i=1;i<=M;i++) ans[i]=(ans[i-1]+a[i])%mod;
cin>>t;
while(t--){
cin>>n;
cout<<ans[n]<<endl;
}
return 0;
}