Codeforces Round 871 (Div. 4)

传送门

A. Love Story

 signed main()
{
    IO;
    int t;cin >> t;
    string ss = "codeforces";
    while(t--)
    {
        string s;cin >> s;
        int cnt = 0;
        for(int i = 0;i < 10;i ++)
        {
            if(s[i] != ss[i])
                cnt ++;
        }
        cout << cnt << endl;
    }
    return 0;
}    

B. Blank Space

signed main()
{
    IO;
    int t; cin >> t;
    while (t--)
    {
        int n; cin >> n;
        vector<int> a(n);
        int ans = 0, cnt = 0;
        for (int i = 0; i < n; i++)
        {
            cin >> a[i];
            if (a[i] != 0) {
                ans = max(ans, cnt);
                cnt = 0;
            }
            else
                cnt++;
        }
        ans = max(ans, cnt);
        cout << ans << endl;
    }
    return 0;
}

C. Mr. Perfectly Fine

题意:有 n n n 本书,每本书可以使你学会 a a a 技能或 b b b 技能,或者同时学会 a , b a, b ab技能。看每本书都有对应的代价,求学会两种技能的最小代价

思路:将书分为只学会 a a a技能和只学会 b b b技能和同时学会 a b ab ab技能,三种类型,用 3 3 3个变量维护三种类型各自的最小代价,最后得到答案。

signed main()
{
    IO;
    int t; cin >> t;
    
    while (t--)
    {
        int n;cin >> n;
        int cnt1 = oo, cnt2 = oo, cnt3 = oo;
        for(int i = 1;i <= n;i ++)
        {
            int ti;cin >> ti;
            string k;cin >> k;
            if(k[0] == '1' && k[1] != '1')
                cnt2 = min(cnt2, ti);
            if(k[0] == '1' && k[1] == '1')
                cnt1 = min(cnt1, ti);
            if(k[0] != '1' && k[1] == '1')
                cnt3 = min(cnt3, ti);
        }
        int ans = min(cnt1, cnt2 + cnt3);
        if(ans >= oo)
            cout << -1 << endl;
        else
            cout << ans << endl;
    }
    return 0;
}

D. Gold Rush

题意:有一堆 n n n个金币,没次操作可以将其分为 a , b a,b a,b两堆,但是二者数量的比值必须为 2 : 1 2:1 2:1,问能否通过一系列操作得到个数为 m m m的堆

思路:
n ∗ ( 1 3 ) p ∗ ( 2 3 ) q = m n * (\frac{1}{3})^p * (\frac{2}{3})^q = m n(31)p(32)q=m
显然
m n = 2 q 3 p + q \frac{m}{n}=\frac{2 ^q}{3^{p+q}} nm=3p+q2q
所以通分 m / n m/n m/n,然后分解 m , n m,n mn的因子,如果 m m m只包含因子 2 2 2 n n n只包含因子 3 3 3,且3的个数大于2的个数就有解

 signed main()
{
    IO;
    int t; cin >> t;
 
    while (t--)
    {
        int n, m;
        cin >> n >> m;
        int d = gcd(m, n);
        int cnt2 = 0, cnt3 = 0;
        m /= d, n /= d;
        // cout << n << ' ' << m << endl;
        while (m % 2 == 0)m /= 2, cnt2++;
        while (n % 3 == 0)n /= 3, cnt3++;
        if (m == 1 && m == n && cnt3 >= cnt2)
            cout << "YES\n";
        else
            cout << "NO\n";
    }
    return 0;
}

E. The Lakes

纯bfs没什么其他的

#include <bits/stdc++.h>
#define oo 0x3f3f3f3f
#define ll long long
#define OO 0x3f3f3f3f3f3f3f3f
#define IO ios::sync_with_stdio(false);cin.tie(nullptr)
#define endl "\n"
#define int ll
const int N = 2e5 + 10, M = 2 * N;
using namespace std;
typedef pair<int, int> pii;
#define deb(i,x) if(int i==x) int k = 1; 
#define all(x) x.begin(),x.end()
ll lowbit(ll x) { return x & -x; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll qmi(ll a, ll b, ll mod) {
    ll res = 1; while (b) { if (b & 1) res = res * a % mod; a = a * a % mod; b >>= 1; }
    return res;
}
int g[1001][1001];
int vis[1001][1001];
int n, m;
int dx[4] = {0,0,-1,1};
int dy[4] = {1,-1,0,0};
int bfs(int x, int y)
{
    int ans = 0;
    queue<array<int, 2>> q;
    q.push({x, y}), vis[x][y] = 1;
    while(q.size())
    {
        auto t = q.front(); q.pop();
        int x = t[0], y = t[1];
        ans += g[x][y];
        for(int i = 0;i < 4;i ++)
        {
            int xx = x + dx[i], yy = y + dy[i];
            if(xx > n || xx < 1 || yy > m || yy < 1)continue;
            if(vis[xx][yy]) continue;
            if(g[xx][yy] > 0)
            {
                vis[xx][yy] = 1;
                q.push({xx, yy});
            }
        }
    }
    return ans;
}
signed main()
{
    IO;
    int t; cin >> t;

    while (t--)
    {
        cin >> n >> m;
        for(int i = 1;i <= n;i ++)
            for(int j = 1;j <= m;j ++)
                cin >> g[i][j], vis[i][j] = 0;
        int ans = 0;
        for(int i = 1;i <= n;i ++)
            for(int j = 1;j <= m;j ++)
            {
                if(!vis[i][j] && g[i][j] > 0)
                    ans = max(ans, bfs(i, j));
            }
        cout << ans << endl;
    }
    return 0;
}

F. Forever Winter

题意:有一个图,其根节点直接与 x x x个节点相邻,而这 x x x个节点每一个又都和 y y y个节点相邻。给定图中的点数和边数和所有边。求 x , y x,y x,y

思路:先求出图的最长直经,找到直径的两个端点,和直径长度。直径的中点就是根节点,它的度数就是 x x x,随便找个根节点直接相邻的节点 n o d e node node,其度数减一就是 y y y

#include <bits/stdc++.h>
#define oo 0x3f3f3f3f
#define ll long long
#define OO 0x3f3f3f3f3f3f3f3f
#define IO ios::sync_with_stdio(false);cin.tie(nullptr)
#define endl "\n"
#define int ll
const int N = 2e5 + 10, M = 2 * N;
using namespace std;
typedef pair<int, int> pii;
#define deb(i,x) if(int i==x) int k = 1; 
#define all(x) x.begin(),x.end()
ll lowbit(ll x) { return x & -x; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll qmi(ll a, ll b, ll mod) {
    ll res = 1; while (b) { if (b & 1) res = res * a % mod; a = a * a % mod; b >>= 1; }
    return res;
}
int n, m;
struct node
{
    int v, ne;
}e[N];
int h[N] = { 0 }, tot = 0;
void add(int u, int v)
{
    e[++tot] = { v, h[u] }; h[u] = tot;
}
int mx1 = 0, id1 = 1, id2;
void dfs(int u, int fa, int de)
{
    if (de > mx1) mx1 = de, id1 = u;
    for (int i = h[u]; i; i = e[i].ne)
    {
        int v = e[i].v;
        if (v == fa)continue;
        dfs(v, u, de + 1);
    }
}

int k, to;
vector<int> ans, tt;
void dfs1(int u, int fa)
{
    if (u == id2) { ans = tt;}
    tt.push_back(u);
    for (int i = h[u]; i; i = e[i].ne)
    {
        int v = e[i].v;
        if (v == fa)continue;
        dfs1(v, u);
        tt.pop_back();
    }
}
signed main()
{
    IO;
    int t; cin >> t;

    while (t--)
    {
        tt.clear();
        tot = 0;
        id1 = 1, id2 = 1;
        mx1 = 0;
        cin >> n >> m;
        for (int i = 1; i <= n; i++)h[i] = 0;
        for (int i = 1; i <= m; i++)
        {
            int u, v; cin >> u >> v;
            add(u, v), add(v, u);
        }
        dfs(1, 0, 0);
        id2 = id1;
        mx1 = 0;
        dfs(id1, 0, 0);
        int de = mx1 + 1;
        k = de / 2 + 1;
        dfs1(id1, 0);
        to = ans[ans.size() / 2];
        int x = 0;
        for (int i = h[to]; i; i = e[i].ne)x++;
        int y = 0;
        for (int i = h[e[h[to]].v]; i; i = e[i].ne) y++;
        cout << x << ' ' << y - 1 << endl;
    }
    return 0;
}

G. Hits Different

题意:有一个塔状结构如图

在这里插入图片描述

对于输入的 n n n,求出直接或间接位于 n n n上方所有部分的和,每部分都是形如 i 2 i^2 i2的值。

思路:记忆化+容斥

对于输入的 n n n,可以用二分求出它所在的层数的上一层是第几层,令其为 k k k

然后就可以分3种情况得到直接位于它上方的部分的值。

  • 第一种

位于当前层的第一个,直接在其上方的部分就一个,值为 k ∗ ( k + 1 ) / 2 − k + 1 k*(k + 1)/2-k+1 k(k+1)/2k+1

  • 第二种

位于当前层最后一个,和第一种类似,其值为 k ∗ ( k + 1 ) k*(k +1 ) k(k+1)/2

  • 第三种

位于当前层第 d d dKaTeX parse error: Undefined control sequence: \and at position 9: d \ne 1 \̲a̲n̲d̲ ̲d\ne最后一个,直接在其上方的有两个。分别为 k ∗ ( k + 1 ) / 2 − k + d k*(k+1)/2-k+d k(k+1)/2k+d k ∗ ( k + 1 ) / 2 − k + d − 1 k*(k+1)/2-k+d-1 k(k+1)/2k+d1

int vis[N] = { 0 };
int get(int n)
{
    int l = 1, r = 1e4;
    while (l < r)
    {
        int mid = (l + r + 1) >> 1;
        if ((mid + 1) * mid / 2 <= n) l = mid;
        else r = mid - 1;
    }
    if (l * (l + 1) / 2 == n) l--;
    return l;
}
int res[N] = { 0 };
 
int dfs(int n)
{
    if (res[n])return res[n];
    int ans = 0;
    int m = n;
    int k = get(m);
    int num = k * (k + 1) / 2;
    int d = m - num;
    ans += m * m;
    int cnt = 0;
    if (d != k + 1)
    {
        cnt++;
        int dd = dfs(num - k + d);
        ans += dd;
    }
    if (d != 1)
    {
        cnt++;
        int dd = dfs(num - k - 1 + d);
        ans += dd;
    }
    if (cnt == 2) {
        int up = num - k + d - 1;
        int floor = get(up);
        num = floor * (floor + 1) / 2;
        d = up - num;
        int dd = dfs(num - floor + d);
        ans -= dd;
    }
    return res[m] = ans;
}
signed main()
{
    IO;
    int t; cin >> t;
 
    while (t--)
    {
        int n; cin >> n;
        for (int i = 1; i <= n; i++)vis[i] = 0;
        vis[n] = 1;
        int ans = dfs(n);
        res[n] = ans;
        cout << ans << endl;
    }
    return 0;
}

H. Don’t Blame Me

DP

signed main()
{
    IO;
    const int mod = 1e9 + 7;
    int t; cin >> t;
    while (t--)
    {
        int n, k; cin >> n >> k;
        vector<int> a(n + 1);
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        vector dp(n + 1, vector<int>(100));
        int ans = 0;
        for(int i = 1; i <= n; i++) {
            dp[i][a[i]] = 1;
            for(int j = 0; j <= 64; j++) {
                dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;
                dp[i][j & a[i]] = (dp[i][j & a[i]] + dp[i - 1][j]) % mod;
        }
    }
        for(int i = 0;i < 64;i ++){
            int d = 0;
            for(int j = 0;j <= 5;j ++)
                if(i & (1 << j)) d ++;
            if(d == k)ans = (ans + dp[n][i]) % mod;
        }
        cout << ans % mod << endl;
    }
    return 0;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值