Codeforces Round #786 (Div. 3)(A-G)

A. Number Transformation

题意:给两个数字 x,y 输出a和b,使得x*b^a = y

思路:令a恒等于1

void solve()
{
	int x, y;
	cin >> x >> y;
	if (y % x == 0) cout << 1 << ' ' << y / x << endl;
	else cout << 0 << ' ' << 0 << endl;
}

B. Dictionary

题意:有一堆由两个不同字母组成的字符串,求当前这个字符串按字典序排第几位

void solve()
{
	cin >> s;
	cout << (s[0] - 'a') * 25 + (s[1] > s[0] ? s[1] - 'a' - 1 : s[1] - 'a') + 1 << '\n';
	return;
}

C. Infinite Replacement

题意:给出一个只包含a的字符串s,和另一个字符串t,可以用t替换掉s中的a,

问能出现多少种字符串

思路:

  1. t等于a,则替换无效,只有一种字符串即s。
  2. t不等于a,并且t中还包含a,那么可以无限叠加,有♾️种字符串
  3. t不包含a,那么对于s中的每个a都可以选择替换或不替换,共有2^s.size()种字符串
void solve()
{
	cin >> s >> t;
    ans = 0;
    if(t == "a") ans = 1;
    else if (t.find('a') != string::npos) ans = -1;
    else ans = (1ll << s.length());
    cout << ans << endl;
        return ;
}

D. A-B-C Sort

题意:给一个原始数组,然后这个数组每次将最后一个数移动到b数组中间,如果b数组当前是奇数长度,那么可以放到中间数的左或右边。a数组为空时,将b数组中间的那个数放到c后面。求这样下来c是否非递减。

思路:两个操作和在一起就是相邻的两个数可以交换,可以倒着遍历,判断能否有序

void solve()
{
    cin >> n;
    fo(i, 0, n - 1) cin >> a[i],b[i]=a[i];
    for(int i = n - 2; i >= 0; i -= 2)
    if(a[i] > a[i + 1]) swap(a[i], a[i + 1]);
    sort(b, b + n);
    fo(i, 0, n - 1)if(b[i] != a[i]){cout << "NO"<

E. Breaking the Wall

题意:可以打一个位置,这个位置每次-2,并且相邻两个位置每次-1,问最少打多少次,可以使任意两个位置为0

思路:暴力枚举三种情况

  1. 打掉相邻的两位置,每次最好可以-3
  2. 打掉相隔一个墙的两位置,每次最好可以-2
  3. 打掉相隔很多墙的两位置,这时只需要找两个最小的位置,上取整即可。
ll t1(ll a, ll b)
{
    if(a < b) swap(a, b);
    if(a > b * 2) return ceil(a*1.0 / 2);
    else return ceil((a + b)*1.0 / 3);
}
ll t2(ll a, ll b)
{
    return ceil((a + b)*1.0/2);
}
ll t3(ll a, ll b)
{
    return ceil(a*1.0/2) + ceil(b*1.0/2);
}
void solve()
{
    cin >> n;
    ans = inf;
    fo(i, 1, n) cin >> a[i];
    fo(i, 2, n) ans = min(ans, t1(a[i], a[i - 1]));
    fo(i, 3, n) ans = min(ans, t2(a[i], a[i - 2]));
    sort(a + 1, a + 1 + n); ans = min(ans, t3(a[1], a[2]));
    cout << ans << endl;
}

F. Desktop Rearrangement

题意:给一个二维数组,其中'*'可以任意移动,问最少移动多少次,可以使得每个'*'的上边和左边全是'*',即从第一列开始依次填满

思路:模拟,记录每一列的'*'数和总'*'数

void solve()
{
    cin >> n >> m >> k;
    fo(i, 1, n) fo(j, 1, m)
    {
        char op;
        cin >> op;
        if(op == '.') g[i][j] = 0 ;else g[i][j] = 1, col[j] ++, res ++;
    }
   // cout << res << endl;
    fo(t, 1, k)
    {
        int x, y;
        cin >> x >> y;
        if(g[x][y]) res --, col[y] -- ;else res ++, col[y] ++ ;
        g[x][y] ^= 1;
        ll c = res / n, r = res % n, in = 0;
        fo(i, 1, c) in += col[i];fo(i, 1, r) in += g[i][c+1];
        cout << res - in << endl;;
    }
}

G. Remove Directed Edges

题意:现在有一幅n个顶点,m条边的有向无环图每个顶点的入度为,出度为,对于每一个点,都要减少它的入度和出度,除非其入度,出度本身为0,并保证剩下的有向图拥有最长路径,最后要求形成一个集合S,S中每一对(u,v)都要求u可达v或者v可达u,并使得S中点数最多。

思路:根据S可以知道,集合S中只有一条链,所以只需要求有向无环图中的最长链

void dfs(int u)
{
    if(f[u]) return;
    f[u] = 1;
    if(out[u] <= 1) return;//出度为1时无法往下转移,长度只能为1
    fo(i, 0, eg[u].size() - 1)
    {
        int j = eg[u][i];dfs(j);
        in[j] > 1 ? f[u] = max(f[u], f[j]+1) : NULL ;
    }
}
void solve()
{
    ans = 0;
    cin >> n >> m;
    fo(i, 1, m)
    {
        int a, b;
        cin >> a >> b;
        eg[a].pb(b), in[b] ++, out[a] ++;
    }
    fo(i, 1, n) dfs(i);
    fo(i, 1, n) ans = max(ans, f[i]);
    cout << ans << endl;
}

你可能感兴趣的:(codeforces,c++,算法)