- 赵一静 的博客
七月暑期集训7月17日DAY8题解
- @ 2024-7-17 8:43:31
小田的同余(数学)
思路
没什么好讲的,直接输出。
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
freopen("mod.in","r",stdin);
freopen("mod.out","w",stdout);
long long n;
cin >>n;
cout <<(n+1)/2;
return 0;
}
小田的奶牛要饿坏啦!!(模拟)
思路没想到的原因
把题目想太简单了,以后不能轻易下结论。
思路
用表示有几天不能吃草,表示能吃几天草,遍历并更新,,最后输出与的最大值即可。
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
freopen("cow.in","r",stdin);
freopen("cow.out","w",stdout);
long long n,t;
cin >>n>>t;
long long ans=0,res=0;
for(long long i=1;i<=n;i++){
long long d,b;
cin >>d>>b;
if(res>=d) res+=b;
else ans+=(d-res-1),res=d+b-1;
}
cout <<max((long long)0,t-ans);
return 0;
}
小田喂猫(pair排序+模拟)
思路没想到的原因
没有时间了,所以没做这题,下次提高做题速度。
思路
可以发现,猫粮可以分成两个部分,第一个部分是在天之内可以吃完,第二个部分是在吃了天后还有剩余的,那么在他们之间就必定有一个整数,来分割他们两部分,而必定会满足这样一个性质:与的前面必定在k天之内可以吃完,在k的后面必定在吃了k天后还有剩余的,我们要可以用二分找到这个数,那就是找出的最后一个数,那就要用二分的第二个模板,除此之外,我们还要使用前缀和来计算区间和,然后用二分找到这个数,最后将他们两加起来输出。
代码
#include <bits/stdc++.h>
using namespace std;
const int tt=1e5+10;
pair<long long,long long> x[tt];
long long a[tt],b[tt];
long long k;
bool cmp(pair<long long,long long> a,pair<long long,long long> b){
return a.second<=b.second;
}
int main(){
freopen("cat.in","r",stdin);
freopen("cat.out","w",stdout);
long long n,q;
cin >>n;
for(long long i=1;i<=n;i++){
cin >>x[i].first;
}
for(long long i=1;i<=n;i++){
cin >>x[i].second;
}
sort(x+1,x+1+n,cmp);
for(long long i=1;i<=n;i++){
a[i]=a[i-1]+x[i].first*x[i].second;
}
for(long long i=n;i>=1;i--){
b[i]=b[i+1]+x[i].first;
}
cin >>q;
while(q--){
long long l=0,r=n;
cin >>k;
while(l<r){
long long mid=(l+r+1)/2;
if(x[mid].second<=k) l=mid;
else r=mid-1;
}
cout <<a[l]+b[l+1]*k<<endl;
}
return 0;
}
小田的打字练习!(模拟)
思路没想到的原因
完全不会。以后多积累题目。
思路
只需注意退格键,其他按题目要求来就行。答案记得计算成时间。
代码
#include <bits/stdc++.h>
using namespace std;
const int tt=1e4+10;
int n,m,T,ans;
char x[tt][tt],y[tt][tt];
int cnt_x[tt],cnt_y[tt];
int main(){
freopen("key.in","r",stdin);
freopen("key.out","w",stdout);
string s,t;
while(1){
n++;
getline(cin,s);
if(s=="\n"){
n--;
continue;
}
if(s=="EOF"){
n--;
break;
}
int i=0;
while(s[i]=='<')i++;
for(;i<s.size();i++){
if(s[i]=='<'){
cnt_x[n]--;
if(cnt_x[n]<0){
cnt_x[n]=0;
}
}else{
x[n][++cnt_x[n]]=int(s[i]);
}
}
}
while(1){
m++;
getline(cin,t);
if(t=="\n"){
m--;
continue;
}
if(t=="EOF"){
m--;
break;
}
int i=0;
while(t[i]=='<')i++;
for(;i<t.size();i++){
if(t[i]=='<'){
cnt_y[m]--;
if(cnt_y[m]<0){
cnt_y[m]=0;
}
}else{
y[m][++cnt_y[m]]=int(t[i]);
}
}
}
cin >>T;
for(int i=1;i<=n;i++){
for(int j=1;j<=cnt_x[i]&&j<=cnt_y[i];j++){
if(x[i][j]==y[i][j]){
ans++;
}
}
}
cout <<(int)(ans*60.0/T+0.5);
}
小田切蛋糕(模拟)
思路没想到的原因
这一题不会做,所以没做出来。当时云里雾里,思绪混乱。不知道怎样判断条件。
思路
接枚举当然会超时,所以我们要用到二分查找个数。最后在计算是否满足条件。
代码
#include<bits/stdc++.h>
using namespace std;
int g[510][510],s[510][510];
int a,b,r,c,qwerty;
bool check(int x){
int flag=0,cnt1=0;
for(int i=1;i<=r;i++){
int cnt2=0,cnt3=0;
for(int j=1;j<=c;j++){
int t=s[i][j]-s[i][cnt3]-s[flag][j]+s[flag][cnt3];
if(t>=x){
cnt3=j;
cnt2++;
}
if(cnt2==b){
cnt1++;
flag=i;
continue;
}
}
if(cnt1==a){
return true;
}
}
return false;
}
int main(){
freopen("cake.in","r",stdin);
freopen("cake.out","w",stdout);
cin >>r>>c>>a>>b;
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
cin >>g[i][j];
s[i][j]=g[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
if(i==r&&j==c){
qwerty=s[i][j];
}
}
}
int l=0,r=qwerty;
while(l<r){
int mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout <<l;
return 0;
}
小田想困住奶牛(模拟)
思路没想到的原因
当时一点思路都没有,我对模拟的运用还不够渗透。以后要多练习。
思路
用两个循环,一个表示奶牛向左冲,另一个表示向右冲。向左冲要向右走,向右冲要向左走,然后计算需要的草,但如果冲出边界,那么循环结束。
代码
#include <bits/stdc++.h>
using namespace std;
const int tt=1e5+10;
pair<int,int> a[tt];
bool cmp(pair<int,int> a,pair<int,int> b){
return a.second<b.second;
}
int main(){
freopen("cow.in","r",stdin);
freopen("cow.out","w",stdout);
int ans=1e9;
int n,b;
cin >>n>>b;
int q=0,w=0;
for(int i=1;i<=n;i++){
cin >>a[i].first>>a[i].second;
}
sort(a+1,a+n+1,cmp);
if(b>a[n].second||b<a[1].second){
cout <<"-1";
return 0;
}
int l=0,r=0,x,y;
for(int i=1;i<=n;i++){
if(a[i].second>b){
w=i,q=i-1;
break;
}
}
l=q;
r=w;
while(l>=1){
while(a[r].second-a[l].second>a[r].first&&r<=n){
r++;
}
if(r>n) break;
ans=min(ans,a[r].second-a[l].second-a[l].first);
l--;
}
l=q;
r=w;
while(r<=n){
while(a[r].second-a[l].second>a[l].first&&l>=1){
l--;
}
if(l<1) break;
ans=min(ans,a[r].second-a[l].second-a[r].first);
r++;
}
if(ans==1e9) cout <<"-1";
else cout <<max(ans,0);
return 0;
}