Codeforces Round 883 (Div. 3) (A ~ G)

A. Rudolph and Cut the Rope

题意:切割一些绳子,让糖果能触碰地面。问切割绳子次数的最小值。

思路:只需要切钉子高度大于绳子长度的绳子。

代码:

写的复杂了点,只用拿一个一变量记录输出即可,太久没打,紧张了。

#include<bits/stdc++.h>

using namespace std;

const int N = 100010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;

void solve()
{
    int n;
    cin >> n;
    vector<int> a(n), b(n);
    for(int i = 0; i < n; i ++ ) cin >> a[i] >> b[i];
    vector<pii> p;
    set<int> st;
    for(int i = 0; i < n; i ++ )
    {
        if(a[i] > b[i]) st.insert(i);
    }
    if(st.size()) cout << st.size() << '\n';
    else cout << 0 << '\n';
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int _;
    _ = 1;
    cin >> _;
    while(_--)
    {
        solve();
    }
    return 0;
}

B. Rudolph and Tic-Tac-Toe

题意:X,+,O能以三个出现在一行,一列,对角线,就输出相应字符,否则输出'DRAW'。

思路:模拟判断即可,一定注意里面还有'.'表示这里什么都没有。

代码:

#include<bits/stdc++.h>

using namespace std;

const int N = 100010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;

char g[10][10];

void solve()
{
    for(int i = 1; i <= 3; i ++ ) cin >> (g[i] + 1);
    for(int i = 1; i <= 3; i ++ )
        if(g[i][1] == g[i][2] && g[i][2] == g[i][3] && g[i][1] != '.') 
        {
            cout << g[i][1] << '\n';
            return ;
        }
        else if(g[1][i] == g[2][i] && g[2][i] == g[3][i] && g[1][i] != '.')
        {
            cout << g[1][i] << '\n';
            return ;
        } 
    if(g[1][1] == g[2][2] && g[2][2] == g[3][3] && g[1][1] != '.') 
    {
        cout << g[1][1] << '\n';
        return ;
    }
    else if(g[1][3] == g[2][2] && g[2][2] == g[3][1] && g[1][3] != '.')
    {
        cout << g[2][2] << '\n';
        return ;
    }
    cout << "DRAW\n";
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int _;
    _ = 1;
    cin >> _;
    while(_--)
    {
        solve();
    }
    return 0;
}

C. Rudolf and the Another Competition

题意:给出每个人做的题的所花时间,求Rudolf(第一个人)能排在第几名,排名规则,以过题数为第一顺序,罚时为第二顺序。如果题数和罚时相同,Rudolf将在最前面。

思路:一个人希望过最多的题,那么一定要先做时间少的题,那么一个人的做题顺序就按照时间从小到大,算出题目数和罚时后,我们可Rudolf的序号(因为Rudolf的序号是1)进行第三顺序,进行排序即可。

代码:

#include<bits/stdc++.h>

using namespace std;

const int N = 100010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;

struct A
{
    ll ct, T, idx;
};

bool cmp(A &a, A &b)
{
    if(a.ct > b.ct) return true;
    else if(a.ct == b.ct)
    {
        if(a.T < b.T) return true;
        else if(a.T == b.T)
        {
            if(a.idx < b.idx) return true;
        }
    }
    return false;
}

void solve()
{
    int n, m, h;
    cin >> n >> m >> h;
    vector<vector<int>> t(n, vector<int>(m));
    vector<ll> sum(n), cnt(n);
    for(int i = 0; i < n; i ++ )
        for(int j = 0; j < m; j ++ ) 
            cin >> t[i][j];
    for(int i = 0; i < n; i ++ )
    {
        sort(t[i].begin(), t[i].end());
        int cur = 0;
        for(int j = 0; j < m; j ++ )
        {
            if(cur + t[i][j] > h) break;
            cnt[i]++; 
            sum[i] += t[i][j] + cur;
            cur += t[i][j];
        }
    }
    vector<A> res(n);
    for(int i = 0; i < n; i ++ )
    {
        res[i] = {cnt[i], sum[i], i};
    }
    sort(res.begin(), res.end(), cmp);
    for(int i = 0; i < n; i ++ )
        if(res[i].idx == 0) 
        {
            cout << i + 1 << '\n';
            break;
        }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int _;
    _ = 1;
    cin >> _;
    while(_--)
    {
        solve();
    }
    return 0;
}

D. Rudolph and Christmas Tree

题意:给一个坐标轴,在上面放三角形求构成图形的面积。

思路:由于可能覆盖,减去重复的面积,用三角形相似减去重复的面积。从下往上放三角形,记录上一个三角形的的上顶点位置hei,底边的位置low,重复的面积是小三角形和给的大三角形进行相似比较可以,设当前的大三角形的底边的位置是y,小三角形的底边x,小三角形的高hei-y,\frac{hei - y}{y} = \frac{x}{d},现在能求出小三角形的底边,那么小三角形面积就求出来了。注意数据类型在计算过程中可能会爆。

代码:

#include<bits/stdc++.h>

using namespace std;

const int N = 100010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;

void solve()
{
    int n;
    double d, h;
    cin >> n >> d >> h;
    ll low = 0, hei = 0;
    double res = 0;
    for(int i = 0; i < n ; i ++ )
    {
        int y;
        cin >> y;
        if(low == 0 && hei == 0)
        {
            res += d * h / 2;
            low = y, hei = y + h;
        }
        else 
        {
            if(y >= hei) 
            {
                res += d * h / 2;
                low = y, hei = y + h;
            }
            else 
            {
                res += d * h / 2;
                res -= (hei - y) * (hei - y) * d / h / 2;
                low = y, hei = y + h;
            }
        }
        // cout << low << ' ' << hei << endl;
        // cout << res << endl;
    }
    printf("%.8lf\n", res);
}

int main()
{
    // ios::sync_with_stdio(0);
    // cin.tie(0);
    int _;
    _ = 1;
    cin >> _;
    while(_--)
    {
        solve();
    }
    return 0;
}

E. Rudolf and Snowflakes

题意:首先一个点,先扩展k条边,再将只连接一条边的点扩展k条边(至少扩展到这),之后可以一直扩展下去,给我们一个n,问能否制作n个点的图形。

思路:首先发现我们1+k^1+k^2+k^3+...+k^p(k > 1,p >= 2),求和\frac{k^{p+1}-1}{k-1},对于easy版本我们n<=1e6,那么枚举用map保存答案即可,范围1<k<=1e3。hard版本,n<=1e18,k的枚举范围就到1<k<=1e9,我们发现对于p>=3,k的枚举范围到1<k<=1e6,我们可以枚举,对于p=2时,我们可以的到公式k^2+k+1=n,判断是否有正整数解并且大于1。

代码:

#include<bits/stdc++.h>

using namespace std;

const int N = 100010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;

set<ll> nums;


// 1 + k + k^1 + ... + k ^ p = (k ^ (p + 1) - 1) / (k - 1)
// 我们能预处理出来的是p >= 3,2 <= k <= 1e6(如果处理p = 2的话,那么p能到达1e9)

void init()
{
    for(ll k = 2; k <= 1000000; k ++ )
    {
        ll val = 1 + k;
        ll p = k * k;
        for(int cnt = 3; cnt <= 63; cnt ++ )
        {
            val += p;
            if(val > 1e18) break;
            nums.insert(val);
            if(p > (ll)(1e18) / k) break;
            p *= k;
        }
    }
}

void solve()
{
    ll n;
    cin >> n;
    if(n < 3) 
    {
        cout << "NO\n";
        return ;
    }
    if(nums.count(n)) 
    {
        cout << "YES\n";
        return ;
    }
    
    //当p = 2时,我们判断k^2 + k + 1 = n是否有正整数解并且大于1
    ll d = 4 * n - 3; //根的判别式
    ll sq = sqrt(d); 
    ll sqd = -1; 
    for(ll i = max(0ll, sq - 5); i <= sq + 5; i ++ ) 
    {
        if(i * i == d) //d能被开方
        {
            sqd = i;
            break;
        }
    }
    //正整数解 (sqd - 1) / 2
    if(sqd != -1 && (sqd - 1) % 2 == 0 && (sqd - 1) / 2 > 1) 
    {
        cout << "YES\n";
    }
    else cout << "NO\n";
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int _;
    _ = 1;
    cin >> _;
    init();
    while(_--)
    {
        solve();
    }
    return 0;
}

F. Rudolph and Mimic

题意:给一堆物品,用数字(1~9)表示,其中有一个模仿者,它能够随意变成某一个物品,它最多只能只能两回合不变,在5个回合内我们要找到它,一个回合中我们可以选着任意个物品将之移除,移除的输出规范在题目中。

思路:分情况讨论,当前的模仿者有两种做法,一是变,二是不变。先看不变,那么就等。如果变,变又分变原来存在的物品和原来不存在的物品。变原来存在的物品就将这种物品保留下来,其他的物品移除掉,这样的话就等它变就行了。变为原来不存在的物品就直接找到。一定在5次内找到,最慢的情况第一次变了,等到第三次变,移除其他的只剩下一种类型物品,等到第5次的时候一定变。

代码:

#include<bits/stdc++.h>

using namespace std;

const int N = 100010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;

int a[10][210];  //存储每层数
int mp[10][20]; //记录每一层某个数出现次数

void solve()
{
    int n;
    cin >> n;
    int cnt = 0;
    vector<int> v;
    a[0][0] = a[1][0] = n;
    memset(mp, 0, sizeof mp);
    while(1)
    {
        cnt++;
        int idx = a[cnt - 1][0];
        v.clear();
        int f = 0; //f = 1时模仿者变化,f = 2时模仿者没变化
        int k = 0; //模仿者变的元素
        for(int i = 1; i <= idx; i ++ ) 
        {
            cin >> a[cnt][i];
            mp[cnt][a[cnt][i]]++;
        }
        if(cnt == 1) 
        {
            cout << "- 0\n";
            continue;
        }

        //和上一层比较,是否有不同
        for(int i = 1; i <= idx; i ++ )
        {
            if(mp[cnt][a[cnt][i]] != mp[cnt - 1][a[cnt][i]]) 
            {
                f = 1;

                //模仿者变成上一层不存在的物品
                if(mp[cnt][a[cnt][i]] && !mp[cnt - 1][a[cnt][i]]) 
                {
                    cout << "! " << i << '\n';
                    return ;
                }
                if(mp[cnt][a[cnt][i]] > mp[cnt - 1][a[cnt][i]]) k = a[cnt][i];
            }
        }
        if(f == 0) f = 2; 

        //模仿者没变,等
        if(f == 2) 
        {
            a[cnt][0] = idx; 
            cout << "- 0\n";
            continue;
        }
        
        //模仿者变成上一层存在的物品,移除元素(模仿者变的元素保存下来)
        if(f == 1) 
        {
            for(int i = 1; i <= idx; i ++ ) 
                if(a[cnt][i] != k) v.push_back(i);
            
            cout << "- " << v.size() << ' ';
            for(auto i : v) cout << i << ' ';
            cout << '\n';

            //移除更新状态
            for(int i = 1; i <= idx - v.size(); i ++ ) a[cnt][i] = k;
            for(int i = 1; i < 10; i ++ ) mp[cnt][i] = 0;
            mp[cnt][k] = idx - v.size();
            a[cnt][0] = idx - v.size();
        }
    }
}

int main()
{
    // ios::sync_with_stdio(0);
    // cin.tie(0);
    int _;
    _ = 1;
    cin >> _;
    while(_--)
    {
        solve();
    }
    return 0;
}

G. Rudolf and CodeVid-23

题意:当前有一种二进制下的字符串每一位表示一种症状(1为有,0为没有),并给出m个其他的字符串,使用后需要等d天后吃其他药,吃完后有相应的症状治疗和副作用,症状治疗相应的位置为1的话治疗该位置的症状,0无效果。副作用相应的位置为1会拥有该症状。问能否痊愈的吃药最短天数,如果不能输出-1。

思路:将它看成从给的状态下到全0的状态的最短路。所有状态为2^10(字符串长度10),用Dijkstra算法。每一个点都可以无限的使用其他的药,如果能到达状态0,即能到达。对于一个状态使用药后转移到另一个状态,当前状态为i,治愈j,副作用k,那么最后的状态i & (~j) | k。

代码:

#include<bits/stdc++.h>

using namespace std;

const int N = 100010, mod = 1e9 + 7, INF = 0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;

void solve()
{
    int n, m;
    cin >> n >> m;
    bitset<10> tmp;
    cin >> tmp;
    int s = tmp.to_ulong();
    vector<pair<pii, int>> edges(m);
    for(int i = 0; i < m; i ++ )
    {
        cin >> edges[i].second;
        cin >> tmp;
        int cur = ((1 << n) - 1) ^ tmp.to_ulong();
        edges[i].first.first = cur;
        cin >> tmp;
        edges[i].first.second = tmp.to_ulong();
    }

    vector<int> dist(1 << n, INF), vis(1 << n);
    dist[s] = 0;
    set<pii> q;
    q.insert({0, s});
    while(q.size())
    {
        auto [d, v] = *q.begin();
        q.erase(q.begin());
        if(vis[v]) continue;
        vis[v] = 1;
        for(int i = 0; i < m; i ++ )
        {
            int to = v & edges[i].first.first;
            to |= edges[i].first.second;
            if(dist[to] > d + edges[i].second) 
            {
                dist[to] = d + edges[i].second;
                q.insert({dist[to], to});
            }
        }
    }
    if(dist[0] == INF) dist[0] = -1;
    cout << dist[0] << '\n';
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int _;
    _ = 1;
    cin >> _;
    while(_--)
    {
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Codeforces Round 894 (Div. 3) 是一个Codeforces举办的比赛,是第894轮的Div. 3级别比赛。它包含了一系列题目,其中包括题目E. Kolya and Movie Theatre。 根据题目描述,E. Kolya and Movie Theatre问题要求我们给定两个字符串,通过三种操作来让字符串a等于字符串b。这三种操作分别为:交换a中相同位置的字符、交换a中对称位置的字符、交换b中对称位置的字符。我们需要先进行一次预处理,替换a中的字符,然后进行上述三种操作,最终得到a等于b的结果。我们需要计算预处理操作的次数。 根据引用的讨论,当且仅当b[i]==b[n-i-1]时,如果a[i]!=a[n-i-1],需要进行一次操作;否则不需要操作。所以我们可以遍历字符串b的前半部分,判断对应位置的字符是否与后半部分对称,并统计需要进行操作的次数。 以上就是Codeforces Round 894 (Div. 3)的简要说明和题目E. Kolya and Movie Theatre的要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Codeforces Round #498 (Div. 3) (A+B+C+D+E+F)](https://blog.csdn.net/qq_46030630/article/details/108804114)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Codeforces Round 894 (Div. 3)A~E题解](https://blog.csdn.net/gyeolhada/article/details/132491891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值