CF 786

A

题意:

给定\(x,y\),求\(a,b\),使得\(y=x*b^a\)

题解:

如果\(y\)\(x\)的倍数,直接输出\(a=1,b=y\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=1e4+7,inf=2e9;
    int n,m,tot;
    int a[N];
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T;cin>>T;
        while(T--)
        {
            int x,y;cin>>x>>y;
            if(x>y||y%x!=0)
            {
                cout<<"0 0\n";
                continue;
            }
            y/=x;
            cout<<1<<' '<<y<<'\n';
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*


*/

B

题意:

给定长度为\(2\)的小写字母字符串,问这个字符串的字典序排名,两位字符不会相同。

题解:

\[(s[0]-'a')*25+(s[1]-'a'+(s[1]<s[0])) \]

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=1e4+7,inf=2e9;
    int n,m,tot;
    int a[N];
    char s[N];
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T;cin>>T;
        while(T--)
        {
            cin>>s;
            int tmp=(s[0]-'a')*25+(s[1]-'a'+(s[1]<s[0]));
            cout<<tmp<<'\n';
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*


*/

C

题意:

给定字符串\(s,t\)\(s\)中只有\(a\),可以把\(s\)中任意一个\(a\)换成\(t\),可以操作任意次,问能换成多少种不同的字符串?

题解:

如果\(t="a"\),那么只有一种。

如果\(|t|>1\)\(t\)中有\(a\),那么有无限种。

否则有\(2^{|s|}\)种。

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=1e4+7,inf=2e9;
    int n,m,tot;
    char s[N],t[N];
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T;cin>>T;
        while(T--)
        {
            cin>>s>>t;
            n=strlen(s),m=strlen(t);
            bool f0=0,f1=0;
            for(int i=0;i<m;++i)
            {
                if(t[i]=='a') f0=1;
                else f1=1;
            }
            if(m==1&&f0)
            {
                cout<<1<<'\n';
                continue;
            }
            if(f0)
            {
                cout<<"-1\n";
                continue;
            }
            cout<<(1ll<<n)<<'\n';

        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*


*/

D

题意:

给定数组\(A\),空数组\(B,C\)

每次把数组\(A\)结尾的元素放到数组\(B\)中间,如果\(B\)长度是奇数可以选择放到中间元素左或右。放完为止。

然后每次从数组\(B\)中间选一个元素,放到数组\(C\)开头。放完为止。

问能否把数组\(C\)变成不下降的。

题解:

这个过程实际上等于把数组\(A\)变成数组\(C\),当数组\(A\)长度为偶数时,可以选择先放第一个还是先放第二个,这个时候选小的放过去,然后再检查\(C\)数组最后是不是不下降。

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=1e4+7,inf=2e9;
    int n,m,tot;
    int a[N],c[N],num;
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T;cin>>T;
        while(T--)
        {
            cin>>n;
            num=0;
            for(int i=1;i<=n;++i)
            {
                cin>>a[i];
            }
            int t=1;
            if(n%2==1) c[++num]=a[t++];
            for(;t<=n;t+=2)
            {
                c[++num]=min(a[t],a[t+1]);
                c[++num]=max(a[t],a[t+1]);
            }
            bool flag=1;
            for(int i=2;i<=num;++i)
            {
                if(c[i-1]>c[i]) flag=0;
            }
            if(flag) cout<<"YES\n";
            else cout<<"NO\n";
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*


*/

E

题意:

有一排墙,第\(i\)个墙坚固度是\(a_i\)

向第\(i\)个墙射击时,第\(i\)个墙坚固度\(-2\)\(i+1,i-1\)个墙坚固度\(-1\)

要摧毁至少两个墙,至少要射击多少发?

题解:

分情况:

\(1.\)干掉两个相关的墙:找两堵坚固度最小的墙分别干掉。

\(2.\)干掉两个相隔一个的墙:先向中间射击,等其中一个被干掉之后射击另一个。

\(3.\)干掉两个相邻的墙:

\(3.1\)当两个墙坚固度差的多时,集中射击坚固度高的就行,然后再往坚固度低的补枪。

\(3.2\)当两个墙坚固度差的不多时,可能会来回射,

设两个墙坚固度分别是\(x,y(x<y)\),对\(y\)的射击次数是\(k\)

\[k+2*(y-2*k)\geq x\\ k\leq \frac{2*y-x}{3} \]

这时射击次数是\(k+max(0,y-2*k)\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=1e4+7,inf=2e9;
    int n,m,tot,ans;
    int a[N],b[N];
    inline int ceil(int x,int y)
    {
        if(x<=0) return 0;
        return (x-1)/y+1;
    }
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T=1;
        while(T--)
        {
            cin>>n;
            ans=inf;
            for(int i=1;i<=n;++i)
            {
                cin>>a[i];
                b[i]=a[i];
            }
            sort(b+1,b+n+1);
            ans=(b[1]-1)/2+1+(b[2]-1)/2+1;
            for(int i=1;i+2<=n;++i)
            {
                int x=a[i],y=a[i+2];
                if(x>y) swap(x,y);
                ans=min(ans,x+ceil(y-x,2));
            }
            for(int i=1;i+1<=n;++i)
            {
                int x=a[i],y=a[i+1];
                if(x>y) swap(x,y);
                int tmp=(y-1)/2+1;
                x-=tmp;x=max(0ll,x);
                
                ans=min(ans,tmp+ceil(x,2));

                int x=a[i],y=a[i+1];
                if(x>y) swap(x,y);
                int tmp=(2*y-x)/3;
                //cout<<tmp<<"!!"<<endl;
                ans=min(ans,tmp+max(0ll,y-2*tmp));
            }
            cout<<ans<<'\n';
            // 11 9
            // 6+2
            // 5+
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*
5
20 10 30 11 9

*/

F

题意:

给一\(n*m\)的方阵,有些位置是\(.\)代表空位,有些位置是\(*\)代表图标。

每次会把一个位置的状态翻转。然后问桌面上的图标都挪到左边,优先填满最靠左的列需要最少多少次移动?

题解:

根据现在桌面上的图标数可以知道桌面上如果靠左填满,会排到什么位置。而本身就在这些位置里面的图标不用动,其他图标都要花一步。

每次会改变桌面上一个位置的状态,那么每次图标的个数只会变化一个,只要看看那个原本应该被填上图标的位置或者新出现的应该被填上图标的位置有没有图标。

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1000+10,mod=1e4+7,inf=2e9;
    int n,m,k,tot,sum;
    int a[N];
    char s[N][N];
    typedef pair<int,int> pr;
    inline int id(int x,int y)
    {
        return (y-1)*n+x;
    }
    inline pr di(int num)
    {
        int x=(num-1)/n+1,y=num%n;
        if(!y) y=n;
        return pr(y,x);
    }
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T=1;
        while(T--)
        {
            cin>>n>>m>>k;
            for(int i=1;i<=n;++i)
            {
                cin>>(s[i]+1);
                for(int j=1;j<=m;++j)
                {
                    tot+=(s[i][j]=='*');
                }
            }
            sum=tot;
            for(int i=1;i<=n;++i)
            {
                for(int j=1;j<=m;++j)
                {
                    if(s[i][j]=='*')
                    {
                        if(id(i,j)<=tot) --sum;
                    }
                }
            }
            for(int i=1;i<=k;++i)
            {
                int x,y;
                cin>>x>>y;
                if(s[x][y]=='*')
                {
                    if(id(x,y)>tot) --sum;
                    s[x][y]='.';
                    pr tmp=di(tot);
                    //cout<<sum<<"!!!!!!!!!!!!!!"<<'\n';
                    //cout<<tmp.first<<' '<<tmp.second<<"!!"<<'\n';;
                    --tot;
                    if(s[tmp.first][tmp.second]=='*') ++sum;
                }
                else
                {
                    ++tot;
                    if(id(x,y)>tot) ++sum;
                    pr tmp=di(tot);
                    if(s[tmp.first][tmp.second]=='*') --sum;
                    s[x][y]='*';
                    //cout<<tmp.first<<' '<<tmp.second<<"!!"<<endl;
                }
                // for(int i=1;i<=n;++i)
                // {
                //     for(int j=1;j<=m;++j)
                //     {
                //         cout<<s[i][j]<<" \n"[j==m];
                //     }
                // }
                cout<<sum<<'\n';
            }
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*


*/

G

题意:

给一个\(DAG\),要求删一些边,然后做到所有点的入度和出度要么为零,要么都减少了,求删完之后的最长路径。

题解:

跑一个拓扑排序,然后只要当前点的出度大于一,指向点的入度大于一,就可以从这里转移。

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=1e4+7,inf=2e9;
    int n,m,tot;
    int a[N];
    vector<int> eg[N];
    int rd[N],cd[N],r[N];
    int dp[N],ans;
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T=1;
        while(T--)
        {
            cin>>n>>m;
            for(int i=1;i<=m;++i)
            {
                int x,y;
                cin>>x>>y;
                eg[x].emplace_back(y);
                ++rd[y];++cd[x];
                ++r[y];
            }
            queue<int> q;
            for(int i=1;i<=n;++i)
            {
                dp[i]=1;
                if(!rd[i])
                {
                    q.push(i);
                }
            }
            while(!q.empty())
            {
                int now=q.front();
                q.pop();
                ans=max(ans,dp[now]);
                for(int t:eg[now])
                {
                    if(r[t]>1&&cd[now]>1) dp[t]=max(dp[t],dp[now]+1);
                    --rd[t];
                    if(!rd[t]) q.push(t);
                }
            }
            cout<<ans<<'\n';
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*
4 5
1 2
2 3
1 4
4 3
4 2


*/
posted @ 2022-05-03 11:28  lovelyred  阅读(31)  评论(0编辑  收藏  举报