Codeforces Round 970 (Div. 3)A~F

nannandbk發表於2024-09-26

Codeforces Round 970 (Div. 3)A~F

A. Sakurako's Exam

把1的個數和2的個數按奇偶分類討論即可。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;
    while(t--)
    {
        int a,b; cin>>a>>b;
        if(a % 2){
            cout<<"NO\n";
            continue;
        }

        if(a % 2 == 0 && b % 2 == 0) cout<<"YES\n";
        else{
            if(a >= 2)
                cout<<"YES\n";
            else cout<<"NO\n";
        }
    }


    return 0;
}

B. Square or Not

對映到矩陣暴力判斷就行了。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    set<int>st;
    int x = 1;
    while(x < N){
        st.insert(x*x);
        x++;
    }

    int t; cin>>t;
    while(t--)
    {
        int n; cin>>n;
        string s; cin>>s;
        if(st.find(n) == st.end()){
            cout<<"No\n";
            continue;
        }

        int m = sqrt(n);
        s = "?" + s;
        char a[m+10][m+10];
        int idx = 0;
        for(int i = 1;i <= m; i++)
        {
            for(int j = 1;j <= m; j++){
                a[i][j] = s[++idx];
            }
        }

        // for(int i = 1;i <= m; i++)
        // {
        //     for(int j = 1;j <= m; j++){
        //         cout<<a[i][j];
        //     }
        //     cout<<"\n";
        // }
        // cout<<"\n";

        bool ok = true;
        for(int i = 1;i <= m; i++)
        {
            if(a[i][1] != '1' || a[i][m] != '1')ok = false;
            if(a[1][i] != '1' || a[m][i] != '1')ok = false;
            if(!ok)break;
        }


        for(int i = 2;i <= m-1; i++)
        {
            for(int j = 2;j <= m-1; j++)
            {
                if(a[i][j] != '0'){
                    ok = false;
                    break;
                }
            }
            if(!ok)break;
        }

        if(!ok)cout<<"No\n";
        else cout<<"Yes\n";

    }


    return 0;
}

C. Longest Good Array

發現是個等差,二分求最多能到哪。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;
    while(t--)
    {
        ll L,R; cin>>L>>R;
        ll l = 1,r = R-L+1;
        while(l <= r)
        {
            ll mid = (l + r)>>1;
            if((1+mid)*mid/2 >= R-L+1)r = mid - 1;
            else l = mid + 1;
        }
        cout<<r + 1<<"\n";
    }


    return 0;
}

D. Sakurako's Hobby

思路:因為是個排列,那麼就不會有多個環連起來的情況。我們畫個圖就能發現,在一個環上的都可相互到達。那麼連通性可以用並查集來維護。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;



int val[N],p[N],siz[N];

int find(int x) {
    return p[x] == x ? x : p[x] = find(p[x]);
}

bool merge(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return false;
    siz[x] += siz[y];
    p[y] = x;
    return true;
}


int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    
    int t; cin>>t;
    while(t--)
    {
        int n; cin>>n;
        for(int i = 1;i <= n; i++)
        {
            int x; cin>>x;
            val[i] = x;
            p[i] = i;
            siz[i] = 1;
        }
        string s; cin>>s;

        s = "?"+s;
        for(int i = 1;i <= n; i++)
        {
            if(p[i] == i){
                bool notself = false;
                int last = i,now = val[i];
                while(1)
                {
                    if(now == i){
                        break;
                    }
                    last = now,now = val[now];
                    // cout<<"last = "<<last<<" now = "<<now<<"\n";
                    
                    merge(last,now);
                }
            }
        }

        map<int,int>mp;
        for(int i = 1;i <= n; i++)
        {
            if(s[i] == '0')//black
            {
               mp[p[i]]++;
            }
        }

        for(int i = 1;i <= n; i++)
        {
            cout<<mp[p[i]]<<" ";
        }
        cout<<"\n";

    }


    return 0;
}

E. Alternating String

思路:因為要求長度是偶數,且奇數位相同,偶數位相同。且刪數操作只能最多一次,那麼肯定是長度奇數的時候必須要用刪數,長度偶數只能進行改數。

我們注意到如果是偶數長度,只考慮該數。統計哪個字母出現最多就行了。

如果是奇數呢?考慮先刪再改。刪哪個呢?我們列舉刪每一個點的代價,且注意到這個被刪的點之後的奇偶性發生互換,寫的時候要小心邊界。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;


char a[N],b[N];
int cnta[N][30],cntb[N][30];
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
  
    int t; cin>>t;
    while(t--)
    {
        int n; cin>>n;
        string s; cin>>s;
        if(n == 1){
            cout<<1<<"\n";
            continue;
        }

        s = "?" + s;
        int n1 = 0,n2 = 0;
        memset(cnta,0,sizeof(a));
        memset(cntb,0,sizeof(b));

        for(int i = 1;i <= n; i++)
        {
            if(i % 2)a[++n1] = s[i];
            else b[++n2] = s[i];
        }

        // for(int i = 1;i <= n1; i++)
        //     cout<<a[i];
        // cout<<"\n";

        // for(int i = 1;i <= n2; i++)
        //     cout<<b[i];
        // cout<<"\n";

        // cout<<"____________________\n";

        for(int i = 1;i <= n1; i++){
            for(int j = 0;j < 26; j++){
                cnta[i][j] = cnta[i-1][j];
            }
            // cout<<"a[i] - 'a' ="<<a[i]-'a'<<"\n";
            cnta[i][a[i]-'a']++;
            // for(int j = 0;j < 26; j++){
            //     cout<<cnta[i][j]<<" ";
            // }
            // cout<<"\n";
        }

        for(int i = 1;i <= n2; i++){
            for(int j = 0;j < 26; j++){
                cntb[i][j] = cntb[i-1][j];
            }
            cntb[i][b[i]-'a']++;
        }

        // cout<<"n = "<<n<<"\n";
        // for(int i = 0;i < 26; i++)
        //     cout<<cnta[n1][i]<<" ";
        // cout<<"\n";
        // for(int i = 0;i < 26; i++)
        //     cout<<cntb[n2][i]<<" ";
        // cout<<"\n";

        if(n % 2 == 0){
            int ans1 = 0,ans2 = 0;
            for(int i = 0;i < 26; i++)
                ans1 = max(ans1,cnta[n1][i]);
            ans1 = n1-ans1;
            for(int i = 0;i < 26; i++)
                ans2 = max(ans2,cntb[n2][i]);
            ans2 = n2-ans2;
            cout<<ans1+ans2<<"\n";
        }else{
            n--;
            int res = 1e9;
            int ans1 = 0,ans2 = 0;

            for(int i = 1;i <= n1; i++){//刪奇數位置
                 // cout<<"i = "<<i<<"\n";
                ans1 = 0,ans2 = 0;
                for(int j = 0;j < 26; j++){
                    // cout<<"j = "<<j<<"\n";
                    
                    ans1 = max(ans1,cnta[i-1][j] + cntb[n2][j]-cntb[i-1][j]);
                    ans2 = max(ans2,cntb[i-1][j] + cnta[n1][j]-cnta[i][j]);

                    // cout<<"cnta[i-1][j] = "<<cnta[i-1][j]<<" cntb[n2][j]-cntb[i-1][j] = "<<cntb[n2][j]-cntb[i-1][j]<<"\n";
                    // cout<<"cntb[n2][j]="<<cntb[n2][j]<<" cntb[i-1][j]="<<cntb[i-1][j]<<"\n";
                    // cout<<"ans1 = "<<ans1<<" ans2 = "<<ans2<<"\n";
                }

                ans1 = n/2-ans1;
                ans2 = n/2-ans2;
                // cout<<"i = "<<i<<" ans1 = "<<ans1<<" ans2 = "<<ans2<<"\n";
                res = min(res,ans1+ans2);
            }

            ans1 = 0,ans2 = 0;
            for(int i = 1;i <= n2; i++){//刪偶數位置
                ans1 = 0,ans2 = 0;
                
                for(int j = 0;j < 26; j++){
                    ans1 = max(ans1,cnta[i][j] + cntb[n2][j]-cntb[i][j]);
                    ans2 = max(ans2,cntb[i-1][j] + cnta[n1][j]-cnta[i][j]);
                }

                ans1 = n/2-ans1;
                ans2 = n/2-ans2;
                // cout<<"i = "<<i<<" ans1 = "<<ans1<<" ans2 = "<<ans2<<"\n";
                res = min(res,ans1+ans2);
            }


            cout<<res+1<<"\n";
        }
    }

    return 0;
}

F. Sakurako's Box

思路:不難發現答案是:\(\dfrac{\sum_{i = 1}^{n-1}\sum_{j = i+1}^na_ia_j}{\dfrac{n(n+1)}{2}}\)

做一個化簡:\(\dfrac{2\times\sum_{i = 1}^{n-1}a_i\sum_{j = i+1}^na_j}{n(n+1)}\)

那麼可以對後面的\(\sum_{j = i+1}^na_j\)做一個字首和的預處理。然後算就行了。取模要千萬小心!當然你也可以直接用python寫。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
ll qmi(ll a, ll b, ll mod)
{
    ll ans = 1 % mod;
    a %= mod;
    while(b)
    {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}


ll a[N];
ll s[N];
ll n;
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;

    while(t--)
    {
        cin>>n;
        ll inv = qmi(n*(n-1),mod-2,mod);

        for(int i = 1;i <= n; i++)
            cin>>a[i];

        for(int i = 1;i <= n; i++)
        {
            s[i] = (s[i-1]+a[i])%mod;
        }

        __int128 ans = 0;
        for(int i = 1;i <= n-1; i++){
            ll t = (s[n]-s[i])%mod;
            if(t < 0) t += mod;
            t %= mod;
            t *= a[i];
            ans = ans + t;
            ans %= mod;
        }

        ans *= 2ll;
        ans %= mod;
        ans *= inv;
        ans %= mod;
        
        cout<<(ll)ans<<"\n";

    }



    return 0;
}

相關文章