Codeforces Round #515 (Div. 3)(A~E题解)

传送门
在这里插入图片描述
在这里插入图片描述
题目大意:
从0~n的路上每个m个距离就有一个灯,现在有一辆火车在路上,挡住了部分灯,问有几个灯可以被看见。

思路:
容斥原则,get(n)-get®+get(l-1)

代码:

#include<bits/stdc++.h>
using namespace std;

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
int n,v,l,r;

int get(int m)
{
    return m/v;
}

void solve()
{    
    cin >> n >> v >> l >> r;
    int ans = get(n) - get(r) + get(l-1);
    cout << ans << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

总结:
读题很久没明白,感谢队友田某某的题意赞助。

传送门
在这里插入图片描述
在这里插入图片描述
题目大意:
给出n个整数代表n个点,0代表当前点没有灯,1代表当前位置有灯。r代表灯的温暖距离。求最少点亮的灯使得所有点都温暖,如果不存在输出-1

思路:
从前向后枚举最远距离的灯使得所有的点都温暖。

代码:

#include<bits/stdc++.h>
using namespace std;

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

int a[1005];
vector<int> v;

void solve()
{
    int n,m;
    cin >> n >> m;
    memset(a,0,sizeof(a));
    for(int i = 1;i <= n;++i) {
        cin >> a[i];
    }
    v.clear();
    for(int i = 1;i <= n;++i) {
        if(a[i] == 1) v.push_back(i);
    }
    bool si = true;
    int k = 1,cnt = 0;
    if(v.size() == 0) {
        cout << -1 << endl;
        return ;
    }
    if(v[0] - 1 > (m-1)) si = false;
    for(int i = 1;i < v.size();++i){
        if(cnt == 0) {
            if(v[i]-k > (m-1)) {
                k = v[i-1];
                cnt++;
            }
        }
        else if(v[i]-k-1 > 2*(m-1)) {
            k = v[i-1];
            cnt++;
        }
        if(v[i]-v[i-1]-1 > 2*(m-1)) si = false;
    }
    //debug(cnt);
    if(n-k > (m-1)) cnt++;
    if(n-v[v.size()-1] > (m-1)) si = false;
    if(!si) cout << -1 << endl;
    else if(cnt == 0) cout << 1 << endl;
    else cout << cnt << endl;
}

int main()
{
    IO;
    int t = 1;
    while(t--){
        solve();
    }
    return 0;
}

总结:
思维水题,一贪到底。

传送门
在这里插入图片描述
在这里插入图片描述
题目大意:
我要被逼疯了,题目大意是从里面抽出q个书重新排列。
而且每一个书都只会拿一次,问书离左右的最短距离。

思路:
模拟跑一边

代码:

#include<bits/stdc++.h>
using namespace std;

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

map<int,int> mp;

void solve()
{
    mp.clear();
    int n;
    cin >> n;
    int cntl = 0,cntr = -1;
    while(n--) {
        char c;
        int m;
        cin >> c >> m;
        switch(c){
            case 'L':
                mp[m] = cntl++;break;
            case 'R':
                mp[m] = cntr--;break;
            case '?':
                cout << min(cntl - 1 - mp[m],mp[m] - cntr - 1) << endl;
                break;
            default:
                break;
        }
    }   
}

int main()
{
    IO;
    int t = 1;
    while(t--){
        solve();
    }
    return 0;
}

总结:
思维水题,当时考虑太复杂了。。。。。

传送门
在这里插入图片描述
在这里插入图片描述题目大意:
每一个袋子大小为k,从后往前装最多装多少个。(如果当前体积装不下,换下一个袋子)

思路:
模拟装袋子的过程

代码:

#include<bits/stdc++.h>
using namespace std;

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

const int maxn = 2e5+10;
int a[maxn];

void solve()
{
    int n,m,k;
    cin >> n >> m >> k;    
    for(int i = 1;i <= n;++i) {
        cin >> a[i];
    }
    int l = k;
    int i;
    for(i = n;i > 0;--i) {
        if(a[i] > l) {
            m--;
            if(m == 0) {
                cout << n-i << endl;
                return ;
            }
            l = k;
            l -= a[i];
        }
        else l-=a[i];
    }
    cout << n << endl;
}

int main()
{
    IO;
    int t = 1;
    while(t--){
        solve();
    }
    return 0;
}

总结:
思维水题,贪心问题

传送门
在这里插入图片描述
在这里插入图片描述
题目大意:
将b每次右移一位,然后与a进行与操作,
将每一次的与操作加和在一起。

思路:
对于a来讲每一位都会与b中位置大于a位置的数字进行一次的与操作,枚举a中每一个1与b与操作的结果。最后加和。

代码:

#include<bits/stdc++.h>
using namespace std;

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

const int mod = 998244353;
vector<int> v;

void solve()
{
    int n,m;
    cin >> n >> m;
    string s1,s2;
    cin >> s1 >> s2;
    reverse(s1.begin(),s1.end());
    reverse(s2.begin(),s2.end());
    v.clear();
    for(int i = 0;i < s2.length();++i) {
        if(s2[i] == '1') v.push_back(i);
    }
    //cout << v[0] << v[1] << v[2] << endl;
    LL ans = 0;
    int j = 0;
    LL sum = 1LL;
    for(int i = 0;i < s1.length();++i) {
        bool si = false;
        for(;j < v.size();++j) {
            if(v[j] >= i) {
                si = true;
                break;
            }
        }
        if(si && s1[i] == '1') {
            //cout << sum  << i << ' ' << j << endl;
            LL nm = sum * (v.size()- j);
            //cout << nm << " " << sum << v.size() << j << endl;
            ans += nm;
            ans %= mod;
        }      
        sum *= 2LL;
        sum %= mod;
    }
    cout << ans << endl;
}

int main()
{
    IO;
    int t = 1;
    while(t--){
        solve();
    }
    return 0;
}

总结:
五个思维水题,在做的过程中最大的感悟就是读题的时候对于题意的理解出现了较大的偏差。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值