现在的位置: 首页 > 综合 > 正文

Codeforces Round #137 (Div. 2)

2018年01月14日 ⁄ 综合 ⁄ 共 3817字 ⁄ 字号 评论关闭

第一题:Shooshuns
and Sequence

题意:给你一个数字序列,有一个操作,1)把第k个数字复制一份放到序列最后。2)删除第1个数字。问要执行多少次操作使得数字序列里的数字都相同,如果不能输出-1

题解:由题目可知,如果原数字序列在第k个数字之后出现不同的数字则不可能通过操作使得数字相同。如果可以使数字都相同,操作数可以通过判断从第i位之后所有数都相同中最小的i即为操作数。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num[100005];
int main()
{
    int n,k;
    bool flag=false;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i)
        scanf("%d",num+i);
    for(int i=n;i>k;--i)
        if(num[i]!=num[k])
        {
            flag=true;
            break;
        }
    if(flag) printf("-1\n");
    else
    {
        int idx=0;
        for(int i=n;i>=1;--i)
            if(num[i]!=num[k])
            {
                idx=i;
                break;
            }
        printf("%d\n",idx);
    }
    return 0;
}

第二题: Cosmic
Tables

题意:一个矩阵,会有交换行或列,以及询问第i行第j列是什么数字的询问。

题解:交换行或列的时候只要交换行列的小标即可,询问就没啥难度了。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int mat[1005][1005];
int row[1005],col[1005];
int main()
{
    int n,m,k;
    char s[5];
    int a,b,temp;
    memset(mat,0,sizeof(mat));
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            scanf("%d",&mat[i][j]);
    for(int i=1;i<=n;++i)
        row[i]=i;
    for(int i=1;i<=m;++i)
        col[i]=i;
    for(;k--;)
    {
        scanf("%s%d%d",s,&a,&b);
        if(s[0]=='c')
        {
            temp=col[a];
            col[a]=col[b];
            col[b]=temp;
        }
        else if(s[0]=='r')
        {
            temp=row[a];
            row[a]=row[b];
            row[b]=temp;
        }
        else
        {
            printf("%d\n",mat[row[a]][col[b]]);
        }
    }
    return 0;
}

第三题: Reducing
Fractions

题意:对于一个分数,为了不让别人很直观的知道是什么,我们把分子用它的几个因子相乘表示,分母也是如此。题目给一个上面提到的那个形式表示的分数,要求对其约分,再通过上面提到的形式把约分后的分数表示出来。

题解:千万不要傻傻的把输入乘起来然后求gcd约分(我比赛时就这样的T^T),这样做不仅数据要超long long而且还费时间。因为题目给的就是分子分母的因子,我们可以在这个基础上继续求因子,同时统计分子和分母的素数因子分别有哪些以及其个数,之后就在各自的素数因子的基础上再约分。这样最后输出的时候也方便快捷。

代码:

#include<cstdio>
#include<cstring>
using namespace std;
int prime[10000005]={0};
int a[100005],b[100005];
int ap[10000005],bp[10000005];
void check(int *x,int *y,int len)//分解因子
{
    for(int i=0;i<len;++i)
        for(int j=x[i];j>1;j/=prime[j])
           y[prime[j]]++;//因子数+1
}
void print(int *x,int *y,int len)
{
    int cnt;
    for(int i=0;i<len;++i)
    {
        cnt=1;
        for(int j=x[i];j>1;j/=prime[j])
            if(y[prime[j]]>0) y[prime[j]]--;
            else              cnt*=prime[j];
        if(i==0) printf("%d",cnt);
        else     printf(" %d",cnt);
    }
    puts("");
}
int main()
{
    int n,m;
    prime[2]=0;
    for(int i=2;i<=10000000;++i)
        if(!prime[i])
        {
            prime[i]=i;
            for(int j=2*i;j<=10000000;j+=i)
                prime[j]=i;
        }
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i) scanf("%d",a+i);
    for(int i=0;i<m;++i) scanf("%d",b+i);
    check(a,ap,n);check(b,bp,m);
    printf("%d %d\n",n,m);
    print(a,bp,n);print(b,ap,m);
    return 0;
}

第四题: Olympiad

题意:有一个n个人参加的比赛,同时Vasya也参加了这个比赛,现在知道第一轮的分数和第二轮的分数,但是不知道这些分数是属于哪个选手的,同时知道Vasya至少获得的分数和k,问Vasya可能的最好名次和最差名次。

题解:题目保证存在分数和大于k,所以Vasya最好成绩就是取分数和最大的第一轮和第二轮分数,即第一名。最差成绩就是第一轮分数和第二轮分数搭配,使得大于等于k的数最多,最差成绩就是取大于等于k中的最小数。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<functional>
using namespace std;
int a[100005],b[100005];
int main()
{
    int n,k,t=1;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i) scanf("%d",a+i);
    for(int i=1;i<=n;++i) scanf("%d",b+i);
    sort(a+1,a+1+n);
    sort(b+1,b+1+n,greater<int>());
    for(int i=1;i<=n;++i)
        if(a[i]+b[t]>=k) ++t;
    printf("%d %d\n",1,t-1);
    return 0;
}

第五题: Decoding
Genome

题意:有个由m中字符组成的长度为n的DNA串,同时告诉你k个不能出现的情况,就是字母b不能接在字母a的后面等等。问符合题目条件的DNA串有多少种,答案对1000000007求余

题解:构造矩阵,直接快速幂就行了。

代码:

#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 55
#define mod 1000000007
#define LL long long
typedef struct node
{
    LL matrix[MAX][MAX];
} Matrix;
Matrix x,y,z;
LL n;//题目的n特别大,必须用long long
int m,k;
int check(char c)
{
    if('a'<=c&&c<='z') return c-'a';
    else               return c-'A'+26;
}
Matrix mul(Matrix a,Matrix b)//矩阵乘法
{
    Matrix c;
    for(int i=0;i<m;++i)
        for(int j=0;j<m;++j)
        {
            c.matrix[i][j]=0;
            for(int k=0;k<m;++k)
                c.matrix[i][j]=(c.matrix[i][j]+(a.matrix[i][k]*b.matrix[k][j])%mod)%mod;
        }
    return c;
}
Matrix cal(LL exp)//矩阵幂
{
    Matrix p,q;
    p=x;
    q=z;//单位矩阵
    for(;exp>1;)
    {
        if(exp&1)
        {
            exp--;
            q=mul(p,q);
        }
        else
        {
            exp>>=1;
            p=mul(p,p);
        }
    }
    p=mul(p,q);
    return p;
}
int main()
{
    char a[5];
    scanf("%I64d%d%d",&n,&m,&k);
    for(int i=0;i<m;++i)
       for(int j=0;j<m;++j)
       {
           x.matrix[i][j]=1;
           z.matrix[i][j]=(i==j);
       }
    for(;k--;)
    {
        scanf("%s",a);
        x.matrix[check(a[0])][check(a[1])]=0;
    }
    if(n==1) y=z;
    else     y=cal(n-1);
    LL ans=0;
    for(int i=0;i<m;++i)
       for(int j=0;j<m;++j)
           ans=(ans+y.matrix[i][j])%mod;
    printf("%I64d\n",ans);
    return 0;
}

来源:http://blog.csdn.net/acm_ted/article/details/7966780

抱歉!评论已关闭.