5.31复习报告

hnsdfzoj 训练

首先声明,水题不首A八百字检讨+重做10遍(有点过了)
否则直接过真的不是我不重视
不知为何,我不喜欢万能头

1001: 最佳方案(本题首A)

题目传送门
我们的目的是要将n变成负数,我们已知n/=2是不可能把n降到0一下,所以必须通过n/=2降到能通过n-=x<0的程度

于是就有了如下代码
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int n,x,t;
int main(){
    cin>>t;
    for(int i=0;i<t;i++){
        cin>>n>>x;
        int sum=0;
        while(n>=0){
            if(n-x<0){
                sum+=1;
                break;
            }
            n=min(n/2,n-x);
            sum+=1;
        }
        cout<<sum<<"\n";
    }
    return 0;
}
完成!

1002: 回文串(本题首A)

题目传送门
本题我们可以先记录不匹配的数量,然后通过输入更改字符串。如果原来匹配现在不匹配,就把不匹配数量+=1;如果原来不匹配现在匹配且不匹配数>0,就把不匹配数–=1;如果原来匹配,现在也匹配,不匹配数不变。

于是就有了如下代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<string>
using namespace std;
string s,tmp;
int n,sum;
int main(){
    cin>>s>>n;
    for(int i=0,j=s.size()-1;i<=j;i++,j--){
        if(s[i]!=s[j])sum++;
    }
    int len=s.size();
    for(int i=0;i<n;i++){
        int p;
        char w;
        cin>>p>>w;
        p--;
        if(s[p]!=s[len-p-1]){
            if(s[len-p-1]==w)sum--;
        }
        else{
            if(len%2==1&&p==len/2);
            else if(s[len-p-1]!=w)sum++;
        }
        if(sum>0)cout<<"No\n";
        else cout<<"Yes\n";
        s[p]=w;
    }
    return 0;
}
完成!

1004: 壁纸(本题3A)

题目传送门
本题真的是一道好题

首先明确一种物极必反 正难则反的思想

意思就是 正着走太麻烦就从后往前走
从前往后的话,每天要看一下前面有没有壁纸可换。复杂度O(n^2)
再看看数据 n<=1e5
n^2<=1e10
显然会TLE (没有数据范围的题目永远是水题 )
首次提交,时间爆炸
二话不说,就来优化
于是就用到了正难则反的思想

正的玩不起就来反的!

于是,我们从后往前的第i天发现今天换了第i天的壁纸后可以用到整个n天结束,就表示今后不能再换,于是dp[i]=1; 但是(没错,我就是那个意外)如果第i天换了壁纸并且后面还可以换壁纸,dp[i]就应该加上后面所有可能的总和
那这个总和怎么算呢?
众所周知,一个东西叫做前缀和
这里我们也是求他的兄弟后缀和!(真兄弟)
因为前面说了dp数组是用来存第i天后(包括第i天)还可以换几次壁纸,于是我们就是求dp的后缀和啦!

于是就有了如下代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<string>
using namespace std;
const int MAXN=1e5+10;
int n;
long long a[MAXN];
long long dp[MAXN];
long long sum[MAXN];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=n;i>=1;i--){
        if(i+a[i]>n)dp[i]=1;
        if(i+a[i]<=n){
            dp[i]=1+sum[i+a[i]];
        }
        sum[i]=(sum[i+1]%1000000007+dp[i]%1000000007)%1000000007;
    }
    cout<<sum[1]%1000000007;
    return 0;
} 
忘了一件大事(你以为就完了吗?)

一定要%1000000007!!!
一定要%1000000007!!!
一定要%1000000007!!!
重要的事情说三遍

完成!

1005: 智力测试题

题目传送门
这题没有首A纯属失误(真的不是我轻视)
除法没用浮点型,并且把t%=(n*n);t++;搞反了(QAQ)

这告诉了我们先++在运算会逝(死的很惨)

直接上代码

Code:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<string>
using namespace std;
int n,t;
int main(){
    cin>>n>>t;
    t%=(n*n);t++;
    int h,l;
    h=t/n+(t%n!=0);
    if(t%n==0)l=n;
    else l=t%n;
    cout<<h<<" "<<l; 
    return 0;
} 
完成!

1007: 飞翔的排列

题目传送门

(说实话这题真的很坑)

因为我们可以发现,不论循环到哪一次总会找到最后一个,所以说不管如何最多也只能飞翔一次

但是(没错,我就是那个意外)

如果最后一个是整个排列的最小值(即为单调递减序列),不能飞翔
(所以说只有1和0两种答案)很坑不是吗?
直接输出1得60分
直接输出0得40分

于是就有了如下代码
#include<cstdio>
#include<iostream>
using namespace std;
int n;
int a;
int minn=0x3f3f3f3f;
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a;
        if(a<minn){
             minn=a;
        }
    }
    if(minn==a)cout<<0;
    else cout<<1; 
    return 0;
}
完成!

1009: 晒衣服与烘干机

题目传送门

这题细节真的超多!

先说几点
1、自然晾干与干衣机不可同时进行
2、干衣机是真的小,每次只能烘一件衣服
3、自然晾干每秒干1的水分,干衣机每秒干k的水分

OK开始吧!

首先看一下数据范围,n<=1e5
这下惨了,暴力O(n^2)过不了,于是
天空一声巨响,二分O(n*log(n))闪亮登场!
我们可以二分答案,即多久可以干掉,然后在check函数中判断这个时间内能否全部晾干,如果可以就记录答案并将时间缩小,如果不行就把时间放大

于是就有了如下代码
#include<iostream>
#include<cmath>
using namespace std;
const int MAXN=1e5+10;
int n,ans;
int a[MAXN];
int k;
int maxa=-0x3f3f3f3f;
bool check(int x){
    long long sum=0;
    for(int i=1;i<=n;i++){
        if(a[i]>x){
            sum+=ceil((a[i]-x)*1.0/(k-1));//注意,k-1可能为0,当k==1时需要特判
        }
    }
    if(sum<=x)return 1;
    else return 0;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]>maxa)maxa=a[i];//记录最大值,特判时需要
    }
    cin>>k;
    if(k==1){//如果干衣机的烘干速度与晾干一样,直接输出最大值
        cout<<maxa;
        return 0;
    }
    int l=1,r=1e9;
    while(l<=r){
        int mid=l+(r-l)/2;
        if(check(mid)){
            ans=mid;
            r=mid-1;
        }else{
            l=mid+1;
        }
    }
    cout<<ans;
    return 0;
}
完成!

1010: 找因数

题目传送门
看题过后,首先想到暴力
但是暴力O(t*n)
肯定过不了
但是,我们知道暴力的一种优化,即n的范围只要找到sqrt(n)即可

于是代码诞生!
#include<iostream>
#include<cmath>
using namespace std;
int t,n;
int main(){
    cin>>t;
    for(int i=0;i<t;i++){
        bool flag=0;
        cin>>n;
        int len=sqrt(n);
        for(int j=2;j<=len;j++){
            if(n%j==0){
                cout<<n/j<<"\n";
                flag=1;
                break;
            }
        }
        if(flag==0)cout<<1<<"\n"; 
    }
    return 0;
}
完成!

1011: 赚金币

题目传送门
本题主要在于进制转换,其他没啥
但是,如果没开long long,就会逝得很惨(44944)

OK,来看一下代码
#include <cstdio>
#include <iostream>
using namespace std;
int t,n,d,k,x;
long long swp(int x,int k){
    long long i=1,h=0;
    while(x>0){
        h+=(x%k)*i;
        x/=k;
        i*=10;
    }
    return h;
}
int main(){
    cin>>t;
    for(int i=0;i<t;i++){
        int sum=0;
        cin>>n>>d>>k>>x;
        for(int j=n;j<n+d;j++){
            long long tmp=swp(j,k);
//          cout<<tmp<<" ";
            while(tmp>0){
                if(tmp%10==x)sum++;
                tmp/=10;
            }
        }
        cout<<sum<<"\n";
    }
    return 0;
}
完成!

1018: 咖啡牛奶

本题是我见到的一道二分好题

题目传送门
我们可以知道1份咖啡牛奶中必须包含以下两种条件。

  • 4份咖啡或牛奶。

  • 至少包含一份咖啡和牛奶。

我们就知道了如何验证是否可组成已知分数的咖啡牛奶

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值