练后补题-codeforces round 962(Div3)

95 阅读9分钟

Codeforces Round 962 (Div. 3)

A.Legs

思路

鸡兔同笼问题,问最少多少只动物就放最多的四条腿的牛就行

Code
1.  #include<bits/stdc++.h>
1.  using namespace std;
1.  #define ll long long
1.  int main(){
1.      ll t,n;
1.      cin >> t;
1.      while(t--){
1.          cin >> n;
            cout << (n/4)+n%4/2 << endl;
1.      }
1.      return 0;
1.  }
翻译题面

在农夫约翰的农场里,今天又是阳光明媚的一天。

农夫约翰到达农场后,他数到了 nn 条腿。已知农场里只养有鸡和牛,其中鸡有 2 条腿,而牛有 4 条腿。

假设农夫约翰已经数完了所有动物的腿,那么农场里至少有多少只动物?

输入

第一行包含一个整数 t1t103t(1≤t≤10³),表示测试案例的数量。

每个测试案例包含一个整数 n2n2103n(2≤n≤2·10³,n 为偶数),表示农夫约翰数到的腿的总数。

输出

对于每个测试案例,输出一个整数,表示农场里动物的最小可能数量。


B.Scale

思路

根据题意纯模拟即可

Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
	ll t;
	cin >> t;
	while(t--){
	    ll n,k;
	    cin >> n >> k;
	    vector<string> arr;
	    for(ll i=0;i<n;++i){
		string str;
		cin >> str;
		arr.push_back(str);
	    }
	    for(ll i=0;i<n;i+=k){
		for(ll j=0;j<n;j+=k)
		    cout << arr[i][j];
		cout << endl;
	    }
	} 
	return 0;
}
翻译题面

蒂娜有一个 n 行 n 列的方格网格,网格中的每个单元格要么是 0,要么是 1。

蒂娜想要将这个网格按k的因子进行缩小( k 是 n 的除数)。为了做到这一点,蒂娜会将网格分割成 k×kk×k 个不重叠的单元格块,使得每个单元格恰好属于一个块。

然后,蒂娜会将每个单元格块替换为一个单独的单元格,该单元格的值等于块中所有单元格的值。保证同一个块中的所有单元格都有相同的值。

例如,下面的演示展示了一个网格被按3的因子进行缩小的情况。

image.png

请帮助蒂娜按k的因子缩小网格。

输入

第一行包含一个整数 t1t100t(1≤t≤100)– 表示测试案例的数量。

每个测试案例的第一行包含两个整数 n 和 k 1n10001kn(1≤n≤1000,1≤k≤n,k 是 n 的除数)– 分别表示网格的行数和列数,以及蒂娜想要按哪个因子缩小网格。

接下来的 n 行,每行包含 n 个字符,描述了网格的单元格。每个字符要么是 0,要么是 1。保证每个 k×kk×k 的块都有相同的值。

保证所有测试案例的 n 的总和不超过1000。

输出

对于每个测试案例,在新的一行上输出按 k 的因子缩小后的网格。


C.Sort

思路

前缀和 先从最开始求每个字符都出现了多少次,然后每次求 llrr 的字符出现次数差的和

Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main() {  
    int t;  
    cin >> t;  
    while (t--) {  
        int n, q;  
        cin >> n >> q;  
        string a, b;  
        cin >> a >> b;  
        vector<vector<int>> freqA(n + 1, vector<int>(26, 0));  
        vector<vector<int>> freqB(n + 1, vector<int>(26, 0));  
        for (int i = 0; i < n; ++i) {  
            freqA[i + 1] = freqA[i];  
            freqB[i + 1] = freqB[i];  
            freqA[i + 1][a[i] - 'a']++;  
            freqB[i + 1][b[i] - 'a']++;  
        }
        while (q--) {  
            int l, r;  
            cin >> l >> r;  
            int operations = 0;  
            for (int i = 0; i < 26; ++i)
                operations += abs(freqA[r][i] - freqA[l - 1][i] - (freqB[r][i] - freqB[l - 1][i]));  
            cout << operations/2 << endl;  
        }  
    }  
    return 0;  
}
题面翻译

你得到了两个长度为 n 的字符串 a 和 b。接下来,你需要回答 q 个查询。

对于每个查询,你会得到一个由 l 和 r 定义的区间。在每次操作中,你可以选择区间 [l,r][l,r] 内的任意位置 iliri(l≤i≤r)并将 aiai 设置为任意字符。你需要输出将 a[l..r]a[l..r] 的排序结果(即 sorted(a[l..r])sorted(a[l..r]))变为与 b[l..r]b[l..r] 的排序结果相同所需的最小操作次数。注意,一个查询中的操作不会影响其他查询。

对于任意字符串 c,sorted(c[l..r])sorted(c[l..r]) 表示由 cl,cl+1,,crcl , cl+1,…, cr 这些字符按字典序排序后形成的子字符串。

输入

  • 第一行包含一个整数 t1t1000t(1≤t≤1000)表示测试用例的数量。
  • 每个测试用例的第一行包含两个整数 n 和 q1n,q2105(1≤n,q≤2⋅10^5),分别表示字符串的长度和查询的数量。
  • 接下来一行是长度为 n 的字符串 a,只包含小写英文字母。
  • 紧接着一行是长度为 n 的字符串 b,也只包含小写英文字母。
  • 之后的 q 行,每行包含两个整数 l 和 r1lrn(1≤l≤r≤n),定义了查询的区间。
  • 保证所有测试用例的 n 和 q 之和不超过 21052⋅10^5

输出

对于每个查询,输出一个整数,表示将 a[l..r] 排序为与 b[l..r] 排序结果相同所需的最小操作次数。


D.Fun

思路

对于所给的两个条件进一步优化得到:c<=xabc<=x-a-bc<=(nab)/(a+b)c<=(n-a*b)/(a+b) 那么 c 可以取从 1 开始到这两个条件的最小值,数据范围也只有 10610^6 可以暴力枚举满足条件的 a 和 b 每次加上满足最小条件的最大的 c 即可

Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline void solve(){
    ll n,x,ans=0;
    cin >> n >> x;
    for(ll a=1;a<=x;a++)
        for(ll b=1;a+b<x && a*b+a+b<=n;b++)
        	ans+=min(x-a-b,(n-a*b)/(a+b));
    cout << ans << endl;
}
int main(){
    int T=1;
    cin >> T;
    while(T--)
        solve();
    return 0;
}
题面大意

给定两个整数 n 和 x,找出满足以下条件的正整数三元组 (a,b,c) 的数量:

  • ab+ac+bcnab+ac+bc≤n
  • a+b+cxa+b+c≤x

注意,顺序是重要的(例如,(1,1,2) 和 (1,2,1) 被视为不同的三元组),并且 a,b,c 必须严格大于 0。

输入:

  • 第一行包含一个整数 t1t104 t(1≤t≤10^4),表示测试用例的数量。
  • 每个测试用例包含两个整数 nn 和 x1n,x106x(1≤n,x≤10^6)
  • 保证所有测试用例的 n 之和不超过 10610^6,所有测试用例的 x 之和也不超过 10610^6

输出:

对于每个测试用例,输出一个整数,表示满足条件的三元组 (a,b,c) 的数量。


E.Decode

思路
  • 对于一段区间 [𝑙,𝑟] ,如果区间内0和1的个数相等那么这个区间对会使答案加 𝑙(𝑛𝑟+1)𝑙∗(𝑛−𝑟+1)
  • 问题就转移成怎么快速求出所有有效区间的位置,这里可以维护一个当前值 now,遇到 0 就减一,遇到 1 就加一,如果一个区间的1和0的数量相同的话,那么这个区间 [𝑙,𝑟] 中 𝑙−1 的当前值和 𝑟 的当前值是相同的
  • 再开一个map来记录每一个i的当前值对应的左部分的和,对于位置为i对答案的贡献就是 𝑚𝑝[𝑛𝑜𝑤](𝑛𝑖+1)𝑚𝑝[𝑛𝑜𝑤]∗(𝑛−𝑖+1)
Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long

int fast_io=[](){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	return 0;

}();

const ll N = 500005, mod = 1e9 + 7;
string s;
ll sum[N];

inline void Decode(){
	cin >> s;
    ll n = s.size();
    for(ll i=0;i<n;++i){
        if(s[i]=='1')
            sum[i+1]=sum[i]+1;
        else
            sum[i+1]=sum[i]-1;
	}
    ll res=0;
    map<ll,ll> mp;
    for(ll x=n;x;--x){
        res=(res+(mp[sum[x-1]]*x)%mod)%mod;
        mp[sum[x]]=(mp[sum[x]]+(n-x+1))%mod;
        res %= mod;
    }
    cout << (res+mod) % mod << endl;
}

int main() {
    ll T;
    cin >> T;
    while(T--)
        Decode();
    return 0;
}
题面大意

在这个问题中,你面临一个挑战,需要从一个游戏的源代码中解码出与角色抽取(gacha system)相关的二进制字符串。为了解码这个字符串,你需要解决一个特定的数学问题。

你得到了一个二进制字符串 s,其长度为 n。对于每一对整数 (l, r)(满足 1 ≤ l ≤ r ≤ n),你需要计算所有 (x, y) 对(其中 l ≤ x ≤ y ≤ r)的数量,使得在这些 (x, y) 范围内的子字符串 sx...sy(即从位置 x 到位置 y 的子串)中,字符 '0' 的数量和字符 '1' 的数量相等。

最后,你需要输出对于所有可能的 (l, r) 对,这些 (x, y) 对的总数的和,结果需要对 10^9 + 7(即 1000000007)取模。

输入

  • 第一行包含一个整数 t1 ≤ t ≤ 1000),表示测试案例的数量。
  • 接下来,每个测试案例包含一个二进制字符串 s1 ≤ |s| ≤ 2 * 10^5),其中 |s| 表示字符串 s 的长度。字符串 s 仅包含字符 '0' 和 '1'
  • 题目保证所有测试案例中的 |s| 之和不超过 2 * 10^5

输出

  • 对于每个测试案例,输出一个整数,即所有 (l, r) 对中满足条件的 (x, y) 对的总数,结果需要对 10^9 + 7 取模。

F.Bomb

思路

这个问题的一个关键观察是,对于每个 ai,我们可能需要多次选择它(特别是当 ai 较大且 bi 相对较小时),直到 ai 减去足够多的 bi 后变为 0 或负数。然而,由于 k 可能非常大(达到 10^9),直接模拟每次操作是不现实的。

一个有效的策略是,对于每个 ai,我们计算它能贡献的总分,这取决于它能在多少次操作中保持非零。具体来说,我们可以计算 (ai / bi) 的上整(即 ai 除以 bi 的商,向上取整),这告诉我们 ai 可以被完全“消耗”多少次(每次消耗 bi)。然后,我们根据 k 的值和这些“消耗次数”来决定选择哪些 ai 以及选择的次数。

由于 k 可能远大于 n,我们需要一种高效的方法来处理这种情况,比如通过排序和贪心算法来选择最优的 ai 进行操作。

示例

假设 n = 3, k = 5, a = [3, 5, 2], b = [1, 2, 1]。

  • 对于 a[1] = 5, b[1] = 2,我们可以从 a[1] 中获取 5/2 = 2 次完整的 bi(即 4 分),并且可能还剩下 1(如果 k 允许)。
  • 对于其他元素,我们可以类似地计算。

最后,我们需要根据 k 的值和每个元素的“贡献潜力”来制定最优的策略。

Code
翻译题面

Sparkle 给了你两个长度为 n 的数组 a 和 b,以及一个整数 k,表示你可以进行的操作次数。初始时,你的得分为 0。在每次操作中,你可以选择一个整数索引 i,并将 ai 加到你的得分上。然后,你必须将 ai 更新为 max(0, ai - bi)。这意味着如果 ai 减去 bi 后仍然非负,则直接减去 bi;如果结果小于 0,则将 ai 设置为 0。

你需要在 k 次操作内,通过选择最佳的操作序列,使得你的最终得分最大化。

输入

  • 第一行包含一个整数 t(1≤t≤1000),表示测试案例的数量。

  • 对于每个测试案例:

    • 第一行包含两个整数 n 和 k(1n2105,1k1091≤n≤2⋅10^5, 1≤k≤10^9),分别表示数组的长度和可以进行的操作次数。
    • 接下来一行包含 n 个整数 a1, a2, ..., an(1ai1091≤ai≤10^9),表示数组 a 的元素。
    • 接下来一行包含 n 个整数 b1, b2, ..., bn(1bi1091≤bi≤10^9),表示数组 b 的元素。
    • 保证所有测试案例的 n 的总和不超过 21052⋅10^5

输出

对于每个测试案例,输出一个整数,表示在 k 次操作后能够获取的最大得分。