Codeforces Round 1027 (Div. 3)(A~G,F和G赛后写的)

A. Square Year

思路:首先用sqrtl去判断是否平方,是就输出0和(ll)sqrtl(n),否则输出-1

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
struct s{
    ll l,r,id;
    friend bool operator<(const s&a,const s&b){
        return a.l>b.l;
    }
};
int main()
{
    fio();
    int t=1;
    cin >> t;
    while (t--)
    {
        string f;
        cin>>f;
        ll cnt=0;
        for(ll i=0;i<f.size();i++)cnt=cnt*10+f[i]-'0';
        ll k=(ll)sqrtl(cnt);
        if(k*k==cnt)cout<<0<<" "<<k<<endl;
        else cout<<-1<<endl;
    }
    return 0;
}

B. Not Quite a Palindromic String

思路:很朴素的拆分串做法,串长度为偶数,所以直接先构造出k,用多的构造,随后再试着0,1一起用,如果最后有剩余就输出NO,否则输出YES

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
struct s{
    ll l,r,id;
    friend bool operator<(const s&a,const s&b){
        return a.l>b.l;
    }
};
int main()
{
    fio();
    int t=1;
    cin >> t;
    while (t--)
    {
        ll n,k;
        cin>>n>>k;
        string f;
        cin>>f;
        ll cn0=0,cn1=0;
        for(ll i=0;i<f.size();i++){
            if(f[i]=='0')cn0++;
            else cn1++;
        }
        ll flag=0;
        while(k>0){
            if(cn0>=cn1){
                if(cn0>=2)cn0-=2;
                else {
                    flag=1;
                    break;
                }
            }
            else if(cn1>=2)cn1-=2;
            else {
                flag=1;
                break;
            }
            k--;
        }
        while(cn0>0&&cn1>0){
        cn0--,cn1--;
        }
        if(cn0||cn1)flag=1;
        if(flag)cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}

C. Need More Arrays

思路:注意数组是非递减的,那么对于同一样的数,其实只要看作一个即可,多的没意义。随后发现要符合数组创建,发现对于去重后的连续段答案为(连续数字长度+1)/2,所以我们把数组划分成多个连续段,然后直接算答案加起来即可。

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
struct s{
    ll l,r,id;
    friend bool operator<(const s&a,const s&b){
        return a.l>b.l;
    }
};
int main()
{
    fio();
    int t=1;
    cin >> t;
    while (t--)
    {
        ll n;
        cin>>n;
        vector<ll>a(n+4);
        for(ll i=1;i<=n;i++)cin>>a[i];
        ll cnt=0;
        ll len=0;
        ll ans=0;
        for(ll i=1;i<=n;i++){
            if(cnt==0)cnt=a[i],len=1;
            else if(a[i]==cnt)continue;
            else if(a[i]==cnt+1)len++,cnt=a[i];
            else {
                ans+=(len+1)/2;
                len=1;
                cnt=a[i];
            }
        }
        ans+=(len+1)/2;
        cout<<ans<<endl;
    }
    return 0;
}

D. Come a Little Closer

思路:不知道删除哪个就枚举所有可能取最小即可,我们可以这样用set<pair<ll,ll>>分别存储行和列的坐标,第一为为数值,第二位为编号。那么特判完n=1后,对于所有可能无非就是移动auto在begin或者rbegin的位置,然后可以算出剩下的坐点构成的矩阵,如果这个矩阵满了,那么我们得长+1或宽+1,两个取个面积min,否则由于有空,我们可以把此时这个点塞进去

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
struct s{
    ll l,r,id;
    friend bool operator<(const s&a,const s&b){
        return a.l>b.l;
    }
};
int main()
{
    fio();
    int t=1;
    cin >> t;
    while (t--)
    {
        ll n;
        cin>>n;
        set<pair<ll,ll>>row,col;
        for(ll i=1;i<=n;i++){
            ll l,r;
            cin>>l>>r;
            row.insert({l,i});
            col.insert({r,i});
        }
        if(n==1){
            cout<<1<<endl;
            continue;
        }
        ll ans=1e18;
        for(ll i=1;i<=n;i++){
            auto miy=row.begin();
            auto may=row.rbegin();
            auto mix=col.begin();
            auto max=col.rbegin();
            if((*miy).second==i)miy++;
            if((*may).second==i)may++;
            if((*max).second==i)max++;
            if((*mix).second==i)mix++;
            ll m1=(*miy).first,m2=(*may).first;
            ll c1=(*mix).first,c2=(*max).first;
            if((m2-m1+1)*(c2-c1+1)!=n-1){
                ans=min(ans,(m2-m1+1)*(c2-c1+1));
            }
            else {
                ans=min(ans,min((m2-m1+2)*(c2-c1+1),(m2-m1+1)*(c2-c1+2)));
            }
            // cout<<i<<" "<<m<<endl;
        }
        cout<<ans<<endl;
    }
    return 0;
}

E. Kirei Attacks the Estate

思路:本质就是维护一个奇性最大连续子序列和偶性最大子序列。所以可以边建树边根据深度设置dp的答案。

d奇数为1否则为0
目前深度为奇性:
\(dp[x][d]=max(dp[x][d]+a[x],dp[fa][d]+a[x]);\)
\(dp[x][d \oplus 1]=max(dp[x][d \oplus 1],dp[fa][d \oplus 1]-a[x]);\)

反之亦然,不会很难

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
struct s{
    ll l,r,id;
    friend bool operator<(const s&a,const s&b){
        return a.l>b.l;
    }
};
int main()
{
    fio();
    int t=1;
    cin >> t;
    while (t--)
    {
        ll n;
       cin>>n;
       vector<ll>a(n+4),g[n+4];
       for(ll i=1;i<=n;i++)cin>>a[i];
       for(ll i=1;i<n;i++){
        ll l,r;
        cin>>l>>r;
        g[l].push_back(r);
        g[r].push_back(l);
       }
       vector<ll>dep(n+5,0);
       vector<vector<ll>>dp(n+5,vector<ll>(2,0));
       vector<ll>ans(n+5);
       function<void(ll,ll)>dfs=[&](ll x,ll fa){
        dep[x]=dep[fa]+1;
        ll d=dep[x]%2;
        if(d&1){
            dp[x][d]=max(a[x],dp[fa][d]+a[x]);
            dp[x][d^1]=max(dp[x][d^1],dp[fa][d^1]-a[x]);
        }
        else {
            dp[x][d]=max(a[x],dp[fa][d]+a[x]);
            dp[x][d^1]=max(dp[x][d^1],dp[fa][d^1]-a[x]);
        }
        for(auto j:g[x]){
            if(j==fa)continue;
            dfs(j,x);
        }
        ans[x]=dp[x][d];
       };
       dfs(1,0);
       for(ll i=1;i<=n;i++)cout<<ans[i]<<" ";
       cout<<endl;
    }
    return 0;
}

F. Small Operations

思路:

特判x=y和k=1的情况。
对于一个大于2的数,其可以被拆成若干质数的乘积。
那么我们先预处理1~1e6内所有数的质数因数,可重复
随后对于给出的x与y分别遍历存储的vector,如果两个大于k的质因数的乘积不相等就输出-1(操作无法解决它)
然后可以认为操作就是x增加某些质数到个数和y相同,y增加某些质数个数和x相同
所以可以得出两个数,注意数为1,其操作数为0
然后写个函数,对进入函数得进行因数分解,存储到vector,
随后单调枚举(类似\(d*d*d\)的复杂度,实际由于d很小且复杂度远远不到这个三次方这个复杂度)从而得出一个数得最优分配。
把得出的两个数经过函数处理得出的相加即可

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
struct s{
    ll l,r,id;
    friend bool operator<(const s&a,const s&b){
        return a.l>b.l;
    }
};
ll zs[2500000];
ll cnt=0;
void ola(ll x)
{
    vector<bool>vis(x+5);
    for(ll i=2;i<=x;i++)
    {
        if(!vis[i])zs[++cnt]=i;
        for(ll j=1;i*zs[j]<=x;j++)
        {
            vis[i*zs[j]]=1;
            if(i%zs[j]==0)break;
        }
    }
}
vector<ll>g[1000005];
int main()
{
    fio();
    int t=1;
    cin >> t;
    ola(1000000);
    for(ll i=1;i<=cnt;i++){
        for(ll j=1;j*zs[i]<=1000000;j++){
            ll u=j*zs[i];
            while(u%zs[i]==0){
            g[j*zs[i]].push_back(zs[i]);
            u/=zs[i];
        }
        }
    }
    while (t--)
    {
        ll x,y,k;
        cin>>x>>y>>k;
        ll kk=max(x,y);
        vector<ll>vis(kk+2,0),vi(kk+2,0);
        if(x==y)cout<<0<<endl;
        else if(k==1)cout<<-1<<endl;
        else {
            ll an1=1,an2=1;
            set<ll>f1,f2;
            ll k1,k2;
            k1=k2=1;
            for(auto j:g[x]){
                if(j>k)k1*=j;
                vis[j]++;
                f1.insert(j);
            }
            for(auto j:g[y]){
                if(j>k)k2*=j;
                vi[j]++;
                f2.insert(j);
            }
            if(k1!=k2)cout<<-1<<endl;
            else {
                function<ll(ll)>ck=[&](ll x){
                    if (x==1)return 0ll;
                    vector<ll>now;
                    for (ll i=1;i*i<=x;i++) {
                        if (x%i==0) {
                            if (i<=k)
                            now.push_back(i);
                            if (x/i!=i&&x/i<=k)now.push_back(x/i);
                        }
                        else if (i>k)break;
                    }
                    sort(now.begin(),now.end());
                    // vector<ll>v(x+5,0),bj(x+4,0);
                    function<ll(ll,ll)>ck1=[&](ll x,ll sz){
                        if (x==0) {
                            if (sz==1)return 0ll;
                            else return (ll)1e18;
                        }
                        else {
                            if (sz==1)return 0ll;
                            ll d=1e18;
                            for (ll j=x;j>=0;j--) {
                                if (sz%now[j]==0) {
                                    d=min(ck1(j,sz/now[j])+1,d);
                                }
                            }
                            return d;
                        }
                    };
                    return ck1((ll)now.size()-1,x);
                };
                for(auto j:f1){
                    if(vi[j]<vis[j]){
                        ll d=vis[j]-vi[j];
                        while(d--){
                            an2*=j;
                        }
                    }
                }
                for(auto j:f2){
                    if(vis[j]<vi[j]){
                        ll d=vi[j]-vis[j];
                        while(d--){
                            an1*=j;
                        }
                    }
                }
                cout<<ck(an1)+ck(an2)<<endl;
            }
        }
    }
    return 0;
}

G. Build an Array

思路:首先k==n即可特判。我们可以思考,对于一个两位数的数组,[c,d]我们无非就是先塞了一个数的一系列数然后另一个数的一系列数优,或者先塞一个数的一部分然后再塞另一个数的一部分优。然后我们就会发现第二种的优秀度<=第一种。

不妨设c<d:
如果c是d除2直到d为奇数上的一个过程数字,
第一种:
如果先构c,再构d。那么由于限制,d必定靠近c的数是c*2,其他位置都可以最小,c可以分解到最小;
如果先构d,再构c。那么d可以分解到最小,c可以分解到最小
第二种:
如果写c的一部分再写d的一部分。那么d会受到c的限制而不能全最小分解
如果写d的一部分再写c的一部分,那么c不能最小分解或者d不能最小分解
如果c不是d除2直到d为奇数上的一个过程数字
我先构d再构c仍是优解
所以综上先构d再构c将是优解。
所以答案肯定是先构大数再延申
做个前缀和后缀和求朴素最大
然后枚举所有位置,将其分解到最小,然后加个前面的前缀和后面的后缀,所有可能取个max即可
如果其大于等于k,那么输出YES,否则输出NO

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
struct s{
    ll l,r,id;
    friend bool operator<(const s&a,const s&b){
        return a.l>b.l;
    }
};
ll zs[2500000];
ll cnt=0;
void ola(ll x)
{
    vector<bool>vis(x+5);
    for(ll i=2;i<=x;i++)
    {
        if(!vis[i])zs[++cnt]=i;
        for(ll j=1;i*zs[j]<=x;j++)
        {
            vis[i*zs[j]]=1;
            if(i%zs[j]==0)break;
        }
    }
}
vector<ll>g[1000005];
int main()
{
    fio();
    int t=1;
    cin >> t;
    while (t--)
    {
        ll n,k;
        cin>>n>>k;
        vector<ll>a(n+4),b(n+4,0);
        for(ll i=1;i<=n;i++)cin>>a[i];
        vector<ll>sub(n+4,0),pre(n+4,0);
        for(ll i=1;i<=n;i++){
            ll u=a[i];
            while(u%2==0){
                u/=2;
            }
            b[i]=u;
        }
        if(n==k)cout<<"YES"<<endl;
        else {
            vector<ll>now(n+5,0);
            a[0]=0,a[n+1]=0;
            ll ans=0;
            for(ll i=1;i<=n;i++){
                ll l=a[i-1];
                ll d=a[i];
                ll sd=0;
                ll flag=0;
                while(d){
                    if(l==d){
                    flag=sd;
                    }
                    if(d&1)break;
                    d/=2;
                    sd++;
                }
                // if(flag){
                //     l=b[i-1];
                //     d=a[i];
                //     sd=0,flag=0;
                //      while(d){
                //     if(l==d){
                //     flag=sd;
                //     }
                //     if(d&1)break;
                //     d/=2;
                //     sd++;
                // }
                // }
                ans=0;
                if(flag==0){
                    ans+=(1ll<<sd);
                }
                else {
                    ans++;
                    ans+=((1ll<<flag-1)-1)*(a[i]/(1ll<<flag-1)/d);
                }
                now[i]=ans;
                // cout<<ans<<endl;
            }
            for(ll i=n;i>=1;i--){
            sub[i]=sub[i+1]+now[i];
            }
             for(ll i=n;i>=1;i--){
                ll l=a[i+1];
                ll d=a[i];
                ll sd=0;
                ll flag=0;
                while(d){
                    if(l==d){
                    flag=sd;
                    }
                    if(d&1)break;
                    d/=2;
                    sd++;
                }
                // if(flag){
                //     l=b[i+1];
                //     d=a[i];
                //     sd=0,flag=0;
                //      while(d){
                //     if(l==d){
                //     flag=sd;
                //     }
                //     if(d&1)break;
                //     d/=2;
                //     sd++;
                // }
                // }
                ans=0;
                if(flag==0){
                    ans+=(1ll<<sd);
                }
                else {
                    ans++;
                    ans+=((1ll<<flag-1)-1)*(a[i]/(1ll<<flag-1)/d);
                }
                now[i]=ans;
            }
            for(ll i=1;i<=n;i++){
                pre[i]=pre[i-1]+now[i];
            }
            ans=0;
           for(ll i=1;i<=n;i++){
            ll d=a[i];
            ll cs=0;
            while(d%2==0){
                cs++;
                d/=2;
            }
            ans=max(ans,pre[i-1]+sub[i+1]+(1ll<<cs));
           }
            // cout<<ans<<endl;
            // cout<<pre[n]<<" "<<sub[1]<<endl;
            if(ans>=k)cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
    }
    return 0;
}
posted @ 2025-05-28 11:37  长皆  阅读(248)  评论(0)    收藏  举报