首页 > 其他分享 >Educational Codeforces Round 38 C- F

Educational Codeforces Round 38 C- F

时间:2023-08-03 17:57:11浏览次数:48  
标签:lfloor Educational 38 frac int ll Codeforces long rfloor

Educational Codeforces Round 38 C - F

https://codeforces.com/contest/938
今天写出了三题ovo

C. Constructing Tests

多画几个图就能发现,对于 \(n\times n\) 的正方形来说,要使得 \(m\times m\) 的子正方形至少有一个 \(0\),则最少的 \(0\) 个数为 \(\lfloor \frac{n}{m} \rfloor ^ 2\)

即最大的 \(1\) 的个数 \(x=n^2-\lfloor \frac{n}{m} \rfloor ^ 2=(n+\lfloor \frac{n}{m} \rfloor)(n-\lfloor \frac{n}{m} \rfloor)\),即化为 \(x\) 的两因子相乘的形式。令 \(a=n+\lfloor \frac{n}{m} \rfloor, b = n-\lfloor \frac{n}{m} \rfloor\),解得 \(n=\frac{a+b}2, \lfloor \frac nm \rfloor =\frac{a-b}2\)

因此只需分解 \(x\),然后判断解出来的 \(n, m\) 是否合法即可。

复杂度为 \(O(t\sqrt x)\)

#include <bits/stdc++.h>
#define ll long long

using namespace std;

void solve () {
    ll x;
    cin >> x;    
    if (x == 0) {
        cout << "1 1\n";
        return ;
    }
    for (ll i = 1; i * i <= x; i++) {
        if (x % i)  continue;
        ll a = i, b = x / i;
        if (a == b || ((a + b) & 1))    continue;
        ll n = (a + b) / 2;
        if (n < 1 || n > 1e9)   continue;
        if (b - a < 2 || b - a > 2 * n || ((b - a) & 1))    continue;
        ll t = (b - a) / 2, m = n / t;
        if (n / m != t)  continue;
        cout << n << ' ' << m << endl;
        return ;
    }
    cout << "-1\n";
}

int main () {
    int t;
    cin >> t;
    while (t--)     solve ();
    // cout << sqrt (1e9);
}

//n^2 - (n / m)^2 = x

D. Buy a Ticket

又是图论小技巧(把点权转化为边权)!!
建立虚拟源点连向 \(n\) 个城市,边权为 \(a_i\),然后因为是往返,所以就把边乘2倍再加进去
建立虚拟源点: 把点权化为源点到点的边权

#include <bits/stdc++.h>
#define ll long long

using namespace std;
typedef pair<ll, int> pii;
const int N = 2e5 + 5, M = N * 4;
int n, m;
int h[N], e[M], ne[M], idx;
ll w[M], d[N], p[N];
bool vis[N];

void add (int a, int b, ll c) {
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

void bfs (int st) {
    priority_queue<pii, vector<pii>, greater<pii>> q;
    q.push ({0, st});
    d[st] = 0;

    while (!q.empty ()) {
        auto t = q.top ();
        q.pop ();
        int ver = t.second;
        ll dist = t.first;
        if (vis[ver])   continue;
        vis[ver] = true;

        for (int i = h[ver]; ~i; i = ne[i]) {
            int j = e[i];
            if (d[j] > dist + w[i]) {
                d[j] = dist + w[i];
                q.push ({d[j], j});
            }
            //else    return ;
        }
    }
}

int main () {
    memset (h, -1, sizeof h);
    memset (d, 0x3f, sizeof d);
    scanf ("%d%d", &n, &m);
    while (m--) {
        int a, b;
        ll c;
        scanf ("%d%d%lld", &a, &b, &c);
        add (a, b, c * 2), add (b, a, c * 2);
    }
    for (int i = 1; i <= n; i++)    scanf ("%lld", &p[i]), add (0, i, p[i]), add (i, 0, p[i]);
    bfs (0);
    for (int i = 1; i <= n; i++)    printf ("%lld ", d[i]);
}

//建立虚拟源点: 把点权化为源点到点的边权

E. Max History

组合数学!又是推柿子qaq

如果发现某几步看不懂的话可能是忘记了这些重要的基础公式!!!!

#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 1e6 + 5, mod = 1e9 + 7;
int a[N], n, maxn;
ll fz = 1, ans, tt;

ll qmi(ll a, ll k, ll p){
    ll res = 1;
    while(k){
        if(k & 1)    res = (ll)res * a % p;
        a = (ll)a * a % p;
        k >>= 1;
    }
    return res;
}

int main () {
    cin >> n;
    for (int i = 1; i <= n; i++)    cin >> a[i], (fz *= i) %= mod;
    sort (a + 1, a + n + 1);
    for (int i = 1; i <= n; i++) {
        if (a[i] == a[n])   break;··
        if (a[i] != a[i-1]) tt = qmi (n - i + 1, mod - 2, mod); //有n-i-1个数比ai小
        (ans += a[i] * fz % mod * tt % mod) %= mod;
    }
    cout << ans << endl;
}

//n!/(n-k)

F. Erasing Substrings

妙妙dp题。
我想到了朴素的状压: \(dp_{i, j}\) 表示考虑到第 \(i\) 位,\(j\) 代表删除的集合(二进制表示)的最小字符串。
然后就不会做了,因为不会用字符串来表示 \(dp\) 数组呜呜。
看了眼题解,说是有个优化:

(link: https://zyd.blog.luogu.org/solution-cf938f)

学到了,这个优化真的很妙。

然后就是滚动数组优化了一下:

#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 5005;
bool f[N]; //f[i][S]; 考虑前i位,S为被删除的集合, 能否等于ans[1...x-len]的bool值
string s;

int main () {
    cin >> s;
    int n = s.size (), k = log2 (n), S = (1 << k);
    memset (f, true, sizeof f);
    for (int i = 0; i < n - S + 1; i++) {
        char ch = 'z';
        for (int j = 0; j < S; j++) {
            for (int x = 0; x < k; x++) {
                f[j | (1 << x)] |= f[j]; //下一步删 2^x
            }
        }
        for (int j = 0; j < S; j++) {
            if (f[j])   ch = min (ch, s[i + j]); //删完这一段之后下一个最小字符
        }
        for (int j = 0; j < S; j++) { //滚动数组
            if (s[i + j] != ch)     f[j] = false; //删去后没法保证前缀相等(为最小)
        }
        cout << ch;
    }
    // cout << log2 (5000);   
}

//O(n^2logn)

G. Shortest Path Queries

complex ds qaq

标签:lfloor,Educational,38,frac,int,ll,Codeforces,long,rfloor
From: https://www.cnblogs.com/CTing/p/17603954.html

相关文章

  • 【安全学习之路】Day38
    ......
  • (*)LeetCode 热题 100 之 238. 除自身以外数组的乘积
    题目给你一个整数数组nums,返回数组answer,其中answer[i]等于nums中除nums[i]之外其余各元素的乘积。题目数据保证数组nums之中任意元素的全部前缀元素和后缀的乘积都在32位整数范围内。请不要使用除法,且在O(n)时间复杂度内完成此题。示例1:输入:nums=......
  • CF938G
    原题翻译老规矩,对于不可做的这种操作题先考虑没有修改操作怎么做这时问题就变为了给你一个联通的图,让你找一条\(u->v\)的最短路我们可以先假设\(u->v\)只有一条简单路径,且权值异或和为d由于原题保证图是联通的,所以我们可以走到图上所有的环,而可以发现我们此时可多得到的贡献......
  • Educational Codeforces Round 104
    https://codeforces.com/contest/1487A.Arena统计与最小值不同的数字数量。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintM=(1<<15)-1;voidsolve(){intn;cin>>n;vector<int>a(n);for(......
  • Educational Codeforces Round 88
    A.BerlandPoker先尽可能的吧小丑给一个人,在把剩下的小丑尽可能的平分,最后计算差值即可。#include<bits/stdc++.h>usingnamespacestd;voidsolve(){intn,m,k,t;cin>>n>>m>>k,t=n/k;inta=min(m,t);m-=a,k--;intb=(m......
  • Codeforces Round 889 (Div. 2) A-E
    传送门,不用谢。A给出排列每次可以交换两个数字,求最少多少次使得排列为错排。考虑在原位的数字个数为\(cnt\)则答案显然为\((cnt+1)>>1\)B求一个最大区间满足其中说有数字被\(n\)整除极其有趣,注意到样例解释具有迷惑性。考虑一个序列\([l,r]\)为答案那么从中可以看出\(1|n......
  • Educational Codeforces Round 152 (Rated for Div. 2)
    Preface经典秒完SB题然后开始坐牢1h,写了个E的假算法T在24个点就不管了打lol去了妈的怎么稍微难点的题就是想不到呢A.MorningSandwich签到#include<cstdio>#include<iostream>#include<utility>#include<vector>#include<cstring>#include<cmath>#include<cstdlib>......
  • Codeforces Round 889 (Div. 2)
    CodeforcesRound889(Div.2)T1​ 思路:我们将\(i\nep_i\)的数量记下来,再判断这个数的奇偶性,如果为偶,那么答案就为这个数/2,如果为奇,那么就是这个数/2+1。T2​ 思路:我们枚举\(1\simn\),我们记录连续是\(n\)的因数的个数,如果不连续了就\(break\),答案就是个数......
  • Codeforces Round 885 (Div. 2)
    CodeforcesRound885(Div.2)A.VikaandHerFriends题目大意太长了click思路可以手动模拟一下,可以发现当两个人的\(x+y\)值就行相同的就能抓到了#include<bits/stdc++.h>usingnamespacestd;intmain(){intT;cin>>T;while(T--){......
  • Codeforces Round 887 (Div. 2)
    CodeforcesRound887(Div.2)A.Desorting题目大意给出一个长度为\(n\)的数组\(a\),可以执行这个操作任意次。选择一下标\(i\),使得\(a_{1...i}\)加上\(1\),\(a_{i+1...n}\)减少\(1\)。问最少几次操作使得数组\(a\)无序。思路首先如果\(a\)原本就无序的......