Codeforces Round #634 (Div. 3)(A~E1) E2待补

题目地址
在这里插入图片描述
t组样例,每个样例一个总数n 要求分成两堆,使得这两堆个数不一样,求组合个数
注意不考虑顺序,即1,3和3,1,是同一个
很明显,少的那一堆最小为1,最大要小于一半,所以奇数时是1到n/2
偶数时是1到(n-1)/2 特判一下0就好了

void solve()
{
    int n=read();
    if(n==1||n==2)
    {
        puts("0");
        return ;
    }
    if(n&1)
    {
        cout<<n/2<<endl;
    }
    else 
    {
        cout<<(n-1)/2<<endl;
    }
}

在这里插入图片描述
t组样例
每个样例给出n,a,b 要求构造出一个长度为n的字符串,使得对于任意长度为a的子序列中不同字符的数目有且只有b个 只能为小写字母且b<=a<=n
我们直接从’a’,‘b’。。。。这样找到一个长度为b的序列,然后不断重复就好了,这样整个字符串内就只有b种字符,且对于任意a的长度都能包含住
(这题a似乎没什么用…

void solve()
{
    int n=read(),a=read(),b=read();
    rep(i,1,n)
    {
        printf("%c",'a'+i%(b));
    }
    cout<<endl;
}

在这里插入图片描述
题意: 给出n个数 要构成两个数组(可以不全用)
要求两个数组大小一样,但一个需要元素全相同,另一个需要元素都不相同,很简单,我们先求出一个有多少个种类的数,然后统计出种类最多的数为多少个
假设m种数,最多的数个数是p 那么答案就是
要么取另外的数 m-1个 最多的数不取 p个 为 tmp1=min(m-1,p)
要么全都取一个 m 个 最多的那个数取p-1个 为tmp2=min(m,p-1)
答案就是 max(tmp1,tmp2)

void solve()
{
    ms(vis,0);
    int n=read();
    int mx=0;
    rep(i,1,n){
        arr[i]=read();
        vis[arr[i]]++;
        mx=max(mx,vis[arr[i]]);
    }
    int num=0;
    int nn=0;
    for(int i=1;i<=n;i++)
    {
        if(vis[i])num++;
 
        if(vis[i]&&vis[i]!=mx){
            vis[i]=1;
        }
        if(vis[i]==mx)
        {
            nn++;
        }
    }
    int a=min(num-1,mx);
    int b=min(num,mx-1);
    cout<<max(a,b)<<endl;
}

在这里插入图片描述
题意: 给出9x9的数独 然后修改成反数独(即每一行至少2个数一样,每一列个需要元素都不相同,很简单,我们先求出一个有多少个种类的数,然后统计出种类最多的数为多少个
假设m种数,最多的数个数是p 那么答案就是要么取另外的数 m-1个 最多的数不取 p个 为 tmp1=min(m-1,p)要么全都取一个 m 个 最多的那个数取p-1个 为tmp2=min(m,p-1)答案就是 max(tmp1,tmp2)cppvoid solve(){ ms(vis,0); int n=read(); int mx=0; rep(i,1,n){ arr[i]=read(); vis[arr[i]]++; mx=max(mx,vis[arr[i]]); } int num=0; int nn=0; for(int i=1;i<=n;i++) { if(vis[i])num++; if(vis[i]&&vis[i]!=mx){ vis[i]=1; } if(vis[i]==mx) { nn++; } } int a=min(num-1,mx); int b=min(num,mx-1); cout<<max(a,b)<<endl;}在这里插入图片描述题意: 给出9x9的数独 然后修改成反数独(即每一行至少2个数一样,每一列,9小区域3x3(也需要至少俩数i相同))
最多修改9处的数 由于最后一个限制条件的存在,所以我们就只能每个小区域修改一个数了
所以就是9行每行修改一个数,且九个数要分别处于9个区域内
假设编号为1到9的小区域
123
456
789
所以我们可以
123分别取第123行的147列
456分别取第456行的258列
789分别取第789行的369列 除了第9列的数赋值成他左边的数其他的都赋值成它右边的数就好了

int ope[10]={0,1,4,7,2,5,8,3,6,9};
void solve()
{
    rep(i,1,9)
    {
        cin>>str[i]+1;
    }
    rep(i,1,9)
    {
        rep(j,1,9)
        {
            arr[i][j]=str[i][j]-'0';
        }
    }
    for(int i=1;i<=9;i++)
    {
        int nx=i,ny=ope[i]+1;
        if(i!=9)
        {
            arr[i][ny-1]=arr[i][ny];
        }
        else 
        {
            ny=ope[i]-1;
            arr[i][ny+1]=arr[i][ny];
        }
    }
    for(int i=1;i<=9;i++)
    {
        for(int j=1;j<=9;j++)
        {
            printf("%d",arr[i][j]);
        }
        puts("");
    }
}

在这里插入图片描述
给出长度n以及n个数的数组,找出一个子序列 使得呈xyx模板
即开头和结尾的区域要一样(元素大小和元素个数都要一样)中间y要求是连续相同的元素组成的区域 xyx都可以为空 求找出最长的xyx这样的三段回文序列
因为easy版数据范围小 所以我直接暴力了一发过了…hard版的有思路了 待补
我就直接dp数组统计每个数左边每个数出现的次数 和右边每个数出现的次数 然后 枚举左右断点 中间区域可以用右端点的左边dp减去左端点的左边 就可以获得中间区域的状态了

int arr[maxn];
int l[maxn][27],r[maxn][27];
void solve()
{
    int n=read();
    rep(i,1,n)
    {
        arr[i]=read();
    }
    if(n==1)
    {
        puts("1");
        return ;
    }
    ms(l,0),ms(r,0);
    for(int i=1;i<=n;i++)
    {
        l[i][arr[i]]++;
        for(int j=1;j<=26;j++)
        {
            l[i][j]+=l[i-1][j];
        }
    }
    for(int i=n;i>=1;i--)
    {
        r[i][arr[i]]++;
        for(int j=1;j<=26;j++)
        {
            r[i][j]+=r[i+1][j];
        }
    }
    int ans=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            int mx1=0,mx2=0;
            for(int k=1;k<=26;k++)
            {
                int a=l[i][k],b=r[j][k];
                mx1=max(mx1,2*min(a,b));
            }
            if(j!=i+1)
            {
                for(int k=1;k<=26;k++)
                {
                    mx2=max(mx2,l[j-1][k]-l[i][k]);
                }
            }
            //de(mx1),de(mx2);//de(mx3);
            ans=max(ans,mx1+mx2); 
        }
    }
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/leoxe/article/details/105536711
今日推荐