简述:

A了5题,相比于上次div3多了一题,也算有进步吧。。。虽然过了5题,但吃了不少罚时,D wa了两次,F wa了四次!! 把这几道题写一下,弄清思路,再补充一些新的想法。(未完待续:

---加了18分,但还没回到最高………… 24.9.2

暂时补完A-F 剩下两题后面再说............ 24.9.3 )

A. Sakurako's Exam

题意:给出a个1和b个2,然后对每个数添加+号或者-号,使得最终的和为0

一开始判断特殊情况,再细分b的数量和a的数量

#include <bits/stdc++.h>
using namespace std;
using LL =  long long;
void solve()
{
    int a,b;
    cin>>a>>b;
    if(a==0 && b==0){
        cout<<"YES"<<endl;
        return;
    }
    if(b%2==0){
        if(a%2==0){
            cout<<"YES"<<endl;
        }
        else{
            cout<<"NO"<<endl;
        }
    }
    else{
        if(a<2){
            cout<<"NO"<<endl;
        }
        else if(a==2){
            cout<<"YES"<<endl;
        }
        else{
            a-=2;
            if(a%2==0){
                cout<<"YES"<<endl;
            }
            else{
                cout<<"NO"<<endl;
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int t ;
    cin>>t;
    while (t--)
    {
        solve();
    }
}

B. Square or Not

题意: 给出一个字符串,由矩阵的每行组成,问是否是美丽矩阵(最外一圈为1,里面为0)的同时是正方形矩阵

先判断字符串长度是否为n的平方 然后再判断美丽矩阵

#include <bits/stdc++.h>
using namespace std;
using LL =  long long;
void solve()
{
    int n;
    cin>>n;
    string s;
    cin>>s;
    int op = n;
    n = sqrt(n);
    char a[n+1][n+1];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            a[i][j]=s[(i-1)*n+j-1];
        }
    }
    int p =0;
    for(int i=1;i<=n;i++){
        if(a[1][i]=='0') p=1;a[1][i]='k';
        if(a[n][i]=='0') p=1;a[n][i]='k';
        if(a[i][1]=='0') p=1;a[i][1]='k';
        if(a[i][n]=='0') p=1;a[i][n]='k';
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(a[i][j]!='k'){
                if(a[i][j]!='0'){
                cout<<"NO"<<endl;
                return;
                }
            }
        }
    }
    int l = sqrt(op);
    if(l*l==op){
        cout<<"YES"<<endl;
    }
    else{
        cout<<"NO"<<endl;
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int t ;
    cin>>t;
    while (t--)
    {
        solve();
    }
}

C. Longest Good Array

给出边界l,r(包含),求出一个数组,满足所有元素在边界值内,且满足数的递增和逐级递增 求数组a的最长长度

以贪心的思路思考,最优的数量就是1 2 4 7这样隔着递增,得到最大数量。 考虑到数的范围为1-1e9,枚举一定会爆时间 再观察得出,以l开始,然后按照+1 +2 +3 逐渐到r,的数量即为答案,可推以l为首项,d=1的等差数量前n项合为r-l 然后枚举n就行了

#include <bits/stdc++.h>
using namespace std;
using LL =  long long;
void solve()
{
    LL l,r;
    cin>>l>>r;
    LL res = r-l;
    int n = 1;
    while(n*(n+1)<=res*2){
        n++;
    }
    cout<<n<<endl;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int t ;
    cin>>t;
    while (t--)
    {
        solve();
    }
}

D. Sakurako's Hobby

给出n个数,然后根据每个ai值,跳到对应点,给出字符串,如果值为0则加一,问1到n每个点最后的值为多少

考虑会有多次重复计算,可以保存一次最大值,然后后续相同点直接赋值复杂度为o(n)

#include <bits/stdc++.h>
using namespace std;
using LL =  long long;
const int N = 2e5+6;
void solve()
{
    int n;
    cin>>n;
    vector<int> a(n+1,0),b(n+1,0),us(n+1,0);
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    string s;
    cin>>s;
    for(int i=1;i<=n;i++){
        if(us[i]) continue;
        int sz = 0;
        while(!us[i]){
            us[i]=1;
            sz+= (s[i-1]=='0');
            i = a[i];
        }
        while(us[i]!=2){
            b[i]=sz;
            us[i]=2;
            i = a[i];
        }
    }
    for(int i=1;i<=n;i++){
        cout<<b[i]<<" ";
    }
    cout<<endl;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int t ;
    cin>>t;
    while (t--)
    {
        solve();
    }
}

E.

F.

赛后重写了一遍,最后wa了5发才弄明白

题意:

从数组中任意取两个数的之积的和为Q ,取的次数为P,求Q/p %mod 的值

运用费马小定理求解,化1/p = pow(p,mod-2)%mod ,然后对于加减的地方要及时%MOD

#include <bits/stdc++.h>
using namespace std;
using LL =  long long;
constexpr int MOD = 1e9+7;
LL kfc(LL x,LL y){
    LL ans = 1;
    while(y){
        if(y&1) ans = ans*x%MOD;
        y >>= 1;
        x = x*x%MOD;
    }
    return ans;
}
void solve()
{
    LL n;
    cin>>n;
    vector<LL> a(n+1,0);
    LL op = 0;
    for(int i=1;i<=n;i++){ 
        cin>>a[i];
        op += a[i];
    }
    LL sum = 0;
    LL pre = 0;
    for(int i=1;i<=n;i++){
        pre+=a[i];
        sum=(sum+a[i]*((op - pre)%MOD))%MOD;
    }
    LL res = LL(n*(n-1)/2)%MOD;
    res = kfc(res,MOD-2);
    cout<<(sum*res)%MOD<<endl;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int t ;
    cin>>t;
    while (t--)
    {
        solve();
    }
}

E. Alternating String

题意:

对于一个字符串修改其为交替字符串所需最小步骤,最多使用一次删除字符操作,任意次交换字符操作, 保证偶数位置字母相同和奇数位置上字母相同,且字符串长度为偶数。

分开判断,对于偶数,无需进行删除操作,只需判断出现字母最大数即可

对于奇数,因为任意位置字符被改变,其后缀字符串奇偶性都会改变,故考虑后缀和 和 前缀和 结合, pre1 + sub2 和 pre2 + sub1

#include <bits/stdc++.h>
using namespace std;
using LL =  long long;
void solve()
{
    int n;
    cin>>n;
    string s;
    cin>>s;
    vector<int> a(27,0),b(27,0);
    for(int i=0;i<s.length();i++){
            if(i%2==0){
                a[s[i]-'a']++;
            }
            else{
                b[s[i]-'a']++;
            }
    }
    if(s.length()%2==0){
        int sum1 = 0,sum2 = 0;
        for(int i=0;i<26;i++){
            sum1 = max(sum1,a[i]); 
            sum2 = max(sum2,b[i]);
        }
        cout<<n/2-sum1+n/2-sum2<<endl;
    }
    else{
        vector<int> pref[2] ={vector<int>(26),vector<int>(26)};
        vector<int> sub[2] = {vector<int>(26),vector<int>(26)};
        for(int i=n-1;i>=0;i--){
            sub[i%2][s[i]-'a']++;
        }
        int res = n+1;
        for(int i=0;i<n;i++){
            sub[i%2][s[i]-'a']--;
            int ans = n;
            for(int k=0;k<2;k++){
                int mx = 0;
                for(int j=0;j<26;j++){
                    mx = max(mx,pref[k][j]+sub[1-k][j]);
                }
                ans -=mx;
            }
            res = min(res,ans);
            pref[i%2][s[i]-'a']++;
        }
        cout<<res<<endl;
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int t ;
    cin>>t;
    while (t--)
    {
        solve();
    }
}