signed

QiShunwang

“诚信为本、客户至上”

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

2021/6/8 23:41:39   来源:

传送门
在这里插入图片描述
在这里插入图片描述
题目大意:
从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;
}

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