牛客周赛 Round 61

Natural-TLP / 2024-09-23 / 原文

A-Letter Song

签到题

代码

#include <iostream>

using namespace std;

int main()
{
    int a, b, c;
    char x;
    cin >> a >> x >> b >> x >> c;
    a += 10;
    
    printf("%04d-%02d-%02d", a, b, c);
}

B-简单图形问题

思路

正方形面积:\(x^2\),正三角形面积:\(\frac{\sqrt{3}}{4} x^2\),判断一下能组成什么就行。

代码

#include <iostream>
#include <cmath>

using namespace std;

typedef long long ll;

int main()
{
    int t;
    cin >> t;
    
    while (t --)
    {
        ll s;
        cin >> s;
        
        ll x = sqrt(s);
        ll y = sqrt(4 * s / sqrt(3));
        
        if (x * x == s && y * y * sqrt(3) / 4 == s) {
            cout << 2 << '\n';
        }
        else if (x * x == s) {
            cout << 0 << '\n';
        }
        else if (y * y * sqrt(3) / 4 == s) {
            cout << 1 << '\n';
        }
        else cout << 3 << '\n';
    }
    return 0;
}

C-小红的差值构造

思路

根据给出的目标点(x, y),如果x>0,显然U操作数量一定要比x值大,否则就不可能到达,同理其他情况也一样。
接下来讨论可行的方案数,同样以x>0的情况讨论,假设用u记录一共有多少个U操作,且U操作一定要选满x个,那么我们就从选则x个开始增加选择的数量,同时也从0开始增加反方向D操作的数量,这样保证最终结果一定到达x。根据组合数概念,就有\(C_{u}^{x+i} * C_{d}^{i}\)搭配的方案数。其他情况同理。

代码

#include <iostream>

using namespace std;

typedef long long ll;

const int mod = 1e9 + 7;
const int M = 1e6;

int n, x, y;
string s;

ll fact[M + 10], infact[M + 10];

ll qmi(int a, int b)
{
    ll res = 1;
    while(b)
    {
        if(b & 1) res = res * a % mod;
        a = (ll)a * a % mod;
        b >>= 1;
    }
    return res;
}

void init()
{
    fact[0] = infact[0] = 1;
    for(int i = 1; i <= M; i ++) fact[i] = fact[i - 1] * i % mod;
    infact[M] = qmi(fact[M], mod - 2); 
    for(int i = M - 1; i >= 1; i --) infact[i] = infact[i + 1] * (i + 1) % mod;
}

ll C(int a, int b)
{
    if(b < 0 || a - b < 0) return 0;
    return fact[a] * infact[b] % mod * infact[a - b] % mod;
}

void solve()
{
    cin >> n >> x >> y;
    cin >> s;
    
    int l = 0, r = 0, d = 0, u = 0;
    for (auto i : s)
    {
        if (i == 'L') l ++;
        if (i == 'R') r ++;
        if (i == 'D') d ++;
        if (i == 'U') u ++;
    }
    
    int L = 0, R = 0, D = 0, U = 0;
    if (x > 0) {
        if (u < x) {
            cout << "NO" << '\n';
            return ;
        }
        U = x;
    }
    else if (x < 0) {
        if (d < abs(x)) {
            cout << "NO" << '\n';
            return ;
        }
        D = abs(x);
    }
    if (y > 0)  {
        if (r < y) {
            cout << "NO" << '\n';
            return ;
        }
        R = y;
    }
    else if (y < 0) {
        if (l < abs(y)) {
            cout << "NO" << '\n';
            return ;
        }
        L = abs(y);
    }
    
    cout << "YES" << ' ';
    
    ll s1 = 0;
    if (x >= 0) {
        for (int i = 0; i <= min(u - U, d); i ++)
            s1 = (s1 + C(u, U + i) * C(d, i) % mod) % mod;
    }
    else {
        for (int i = 0; i <= min(d - D, u); i ++)
            s1 = (s1 + C(d, D + i) * C(u, i) % mod) % mod;
    }
    
    ll s2 = 0;
    if (y < 0) {
        for (int i = 0; i <= min(l - L, r); i ++)
            s2 = (s2 + C(l, L + i) * C(r, i) % mod) % mod;
    }
    else {
        for (int i = 0; i <= min(r - R, l); i ++)
            s2 = (s2 + C(r, R + i) * C(l, i) % mod) % mod;
    }
    
    for (int i = 0; i < n; i ++)
    {
        if (U && s[i] == 'U') {
            cout << s[i];
            U --;
        }
        if (D && s[i] == 'D') {
            cout << s[i];
            D --;
        }
        if (L && s[i] == 'L') {
            cout << s[i];
            L --;
        }
        if (R && s[i] == 'R') {
            cout << s[i];
            R --;
        }
    }
    
    cout << ' ' << s1 * s2 % mod << '\n';
}

int main()
{
    init();
    int t;
    cin >> t;
    while (t --) solve();
    
    return 0;
}

D-小红的差值构造

思路

根据题意,就是到x和y两个点的最短距离之和的最小值。分情况讨论一下,要么x和y都在1~n以内,要么一个在外面,一个在里面。很显然的,要贪最小,就是位置最中间的时候(证明不会),第一个情况,x为\(mid-\frac{l}{2}\)、y为\(mid+\frac{l}{2}\),第二个情况,x为mid、y为mid+l,取这两个值的最小值。

代码

#include <iostream>

using namespace std;

typedef long long ll;

int n, l;

ll s(ll x)
{
    return x * (x + 1) / 2;
}

ll func(ll x) 
{
    if (x % 2) return s(x / 2 + 1) + s(x / 2);
    else return s(x / 2) * 2;
}

void solve()
{
    cin >> n >> l;
    
    int mid = (n + 1) / 2;
    int x = mid - l / 2, y = x + l;
    
    ll res = s(x - 1) + s(n - y) + func(y - x - 1);
    ll ans = func(n - 1);
    if (ans < res) cout << mid << ' ' << mid + l << ' ' << ans << '\n';
    else cout << x << ' ' << y << ' ' << res << '\n';
}

int main()
{
    int t;
    cin >> t;
    while (t --) solve();
    
    return 0;
}