Codeforces Round #258 (Div. 2)-(A,B,C,D,E)

http://blog.csdn.net/rowanhaoa/article/details/38116713

A:Game With Sticks

水题。。。每次操作,都会拿走一个横行,一个竖行。

所以一共会操作min(横行,竖行)次。

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define mem(a,b) (memset(a),b,sizeof(a))
#define lmin 1
#define rmax n
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define root lmin,rmax,1
#define now l,r,rt
#define int_now int l,int r,int rt
#define INF 99999999
#define LL __int64
#define mod 1000000009
#define eps 1e-6
#define zero(x) (fabs(x)<eps?0:x)
#define maxn 330000
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        int y=min(n,m);
        if(y%2)cout<<"Akshat"<<endl;
        else cout<<"Malvika"<<endl;
    }
    return 0;
}

B:Sort the Array

给数组中的每一个数字标号,标记他应该出现在哪一个位置。

然后从头往后找,如果当前位置的数字不是应该在这个位置的数字。

那么就找到应该在这个位置的数字的位置,然后翻转。如果还不是按顺序排的话,就输出no,否则输出yes。

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define mem(a,b) (memset(a),b,sizeof(a))
#define lmin 1
#define rmax n
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define root lmin,rmax,1
#define now l,r,rt
#define int_now int l,int r,int rt
#define INF 99999999
#define LL __int64
#define mod 1000000009
#define eps 1e-6
#define zero(x) (fabs(x)<eps?0:x)
#define maxn 110000
struct list
{
    int x;
    int id;
    int y;
}node[maxn];
int cmp1(list a,list b)
{
    return a.x<b.x;
}
int cmp2(list a,list b)
{
    return a.id<b.id;
}
int main()
{
    int n,m;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&node[i].x);
            node[i].id=i;
        }
        sort(node+1,node+n+1,cmp1);
        for(int i=1;i<=n;i++)node[i].y=i;
        sort(node+1,node+n+1,cmp2);
        int st,ed,i;
        st=ed=-1;
        for(i=1;i<=n;i++)
        {
            if(node[i].y!=i)
            {
                if(st==-1)
                {
                    int j,k;
                    for(j=i+1;j<=n;j++)
                    {
                        if(node[j].y==i)break;
                    }
                    for(k=j;k>=i;k--)
                    {
                        if(node[k].y!=i+(j-k))break;
                    }
                    if(k>=i)break;
                    st=i;
                    ed=j;
                    i=j+1;
                }
                else break;
            }
        }
        if(i<=n)cout<<"no"<<endl;
        else
        {
            cout<<"yes"<<endl;
            if(st!=-1)cout<<st<<" "<<ed<<endl;
            else cout<<"1 1"<<endl;
        }
    }
    return 0;
}

C:Predict Outcome of the Game

枚举两个差值的正负号。

对于每一种情况:

可以算出A,B,C最少赢几个球。然后看看当前的赢球数是不是符合K。

然后看一下差值是否可以用(n-k)消除掉。

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define mem(a,b) (memset(a),b,sizeof(a))
#define lmin 1
#define rmax n
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define root lmin,rmax,1
#define now l,r,rt
#define int_now int l,int r,int rt
#define INF 99999999
#define LL __int64
#define mod 1000000009
#define eps 1e-6
#define zero(x) (fabs(x)<eps?0:x)
#define maxn 110000
struct list
{
    int x;
    int id;
    int y;
}node[maxn];
int cmp1(list a,list b)
{
    return a.x<b.x;
}
int cmp2(list a,list b)
{
    return a.id<b.id;
}
int pan(LL n,LL k,LL d1,LL d2)
{
    LL a,b,c;
    a=0;
    b=a+d1;
    c=b+d2;
    LL d;
    d=min(a,min(b,c));
    if(d<0)
    {
        d=-d;
        a+=d;
        b+=d;
        c+=d;
    }
    d=max(a,max(b,c));
    LL cha=0;
    cha=a+b+c;
    cha=k-cha;
    if(cha<0)return 0;
    if(cha%3)return 0;
    cha=0;
    cha+=d-a;
    cha+=d-b;
    cha+=d-c;
    LL cun=n-k;
    cun=cun-cha;
    if(cun<0)return 0;
    if(cun%3==0)
    {
     //   cout<<n<<" "<<k<<" "<<d1<<" "<<d2<<endl;
        return 1;
    }
    else return 0;
}
void dos()
{
    LL n,k,d1,d2;
    cin>>n>>k>>d1>>d2;
    LL a,b,c;
    a=0;
    if(pan(n,k,d1,d2))
    {
        cout<<"yes"<<endl;
        return;
    }
    if(pan(n,k,-d1,d2))
    {
        cout<<"yes"<<endl;
        return;
    }
    if(pan(n,k,d1,-d2))
    {
        cout<<"yes"<<endl;
        return;
    }
    if(pan(n,k,-d1,-d2))
    {
        cout<<"yes"<<endl;
        return;
    }
    cout<<"no"<<endl;
}
int main()
{
    int t;
    LL n,k,d1,d2;
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            dos();
        }
    }
    return 0;
}

D:Count Good Substrings

假如字符串为:abbabbbaaa

我们把这个字符串如下记录:

字符串: a b a b a

数组num :1 2 1 3  3

数组的每一项代表这个字符串这个位置的字符是由几个字符压缩成的。

对于回文串的两边都是a的情况:

预处理从起点走奇数步可到达多少a,走偶数步,可到达多少a。

然后从第一个a往后走,可在O(1)的复杂度内得出当前a的为回文串的左边,一共有几个奇数子串,几个偶数子串。

对于回文串的两边都是b的情况,类似与两边都是a的情况。

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define mem(a,b) (memset(a),b,sizeof(a))
#define lmin 1
#define rmax n
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define root lmin,rmax,1
#define now l,r,rt
#define int_now int l,int r,int rt
#define INF 99999999
#define LL __int64
#define mod 1000000009
#define eps 1e-6
#define zero(x) (fabs(x)<eps?0:x)
#define maxn 110000
LL a[maxn];
char str[maxn];
vector<char>vec;
int num[maxn];
LL s1,s2;
LL cal(int x,int y)
{
    if(x<0)return 0;
    LL a1,an,n;
    if(y==1)
    {
        if(x<2)return 0;
        an=x-1;
        if(x%2)a1=2;
        else a1=1;
        n=(an-a1)/2+1;
        return n*(a1+an)/(LL)2;
    }
    else
    {
        an=x;
        if(x%2)a1=1;
        else a1=2;
        n=(an-a1)/2+1;
        return n*(a1+an)/(LL)2;
    }
}
void dos(int x)
{
    int n=vec.size();
    LL even,odd;
    even=odd=0;
    LL sum=0;
    for(int i=1; i<=n; i++)
    {
        if(i%2==x)
        {
            LL a,b;
            a=num[i]/2;
            b=num[i]-a;
            if(sum%2)swap(a,b);
            even+=a;//偶
            odd+=b;//奇
        }
        sum+=num[i];
    }
    sum=0;
    for(int i=x;i<=n;i+=2)
    {
        LL a,b;
        a=num[i]/2;
        b=num[i]-a;
        if(sum%2)swap(even,odd);
        sum=0;
        even-=a;
        odd-=b;
        sum+=num[i];
        if(sum%2)swap(even,odd);
        sum=0;
        s1+=b*odd;
        s1+=a*even;
        s2+=b*even;
        s2+=a*odd;
        s1+=cal(num[i],1);
        s2+=cal(num[i],2);
        sum+=num[i+1];
    }
}
int main()
{
    int n;
    LL s;
    while(~scanf("%s",str))
    {
        vec.clear();
        int len=strlen(str);
        int s=1;
        for(int i=1; i<len; i++)
        {
            if(str[i]!=str[i-1])
            {
                vec.push_back(str[i-1]);
                num[vec.size()]=s;
                s=1;
            }
            else s++;
        }
        vec.push_back(str[len-1]);
        num[vec.size()]=s;
        s1=s2=0;
        dos(1);
        dos(0);
        cout<<s1<<" "<<s2<<endl;
    }
    return 0;
}

E:Devu and Flowers

做这个题目出了一些莫名其妙的问题。。

做法:

如果每一个每一种花都有无限个,很明显,有C(s+n-1,n-1)种取法。

如果某种花取x个以上,那么就有C(s+n-1-x-1,n-1)种取法。

所以就用到容斥:

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
using namespace std;
#define maxn 21
#define LL __int64
#define mod 1000000007
LL num[21];
LL inv[21];
void gcd(LL a, LL b, LL& d, LL& x, LL& y) {
    if(!b){ d = a; x = 1; y = 0; }
    else{ gcd(b, a%b, d, y, x); y -= x*(a/b); }
}

LL getInv(LL a, LL n) {
    LL d, x, y;
    gcd(a, n, d, x, y);
    return d == 1 ? ( x + n ) % n : -1;
}
LL com(LL n,LL m)
{

    if(n<m)return 0;
    LL ans;
    ans=1;
    for(LL i=n;i>=(n-m+1);i--)
    {
        ans=ans*(i%mod)%mod;
        ans=ans*inv[n-i+1]%mod;
    }
    return ans;
}
int main()
{
    LL n,s;
    for(int i=1;i<=20;i++)inv[i]=getInv(i,mod);
    while(~scanf("%I64d%I64d",&n,&s))
    {
        LL r=0;
        int m=n;
        for(int i=0;i<m;i++)
        {
            scanf("%I64d",&num[i]);
        }
        LL ans=com(s+n-1,n-1);
        for(int i=1;i<(1<<m);i++)
        {
            int x=0;
            r=0;
            for(int j=0;j<m;j++)
            {
                if(i&(1<<j))
                {
                    x++;
                    r+=num[j]+1;
                }
            }
            if(x&1)
            {
                ans-=com(s-r+n-1,n-1);
                ans=(ans%mod+mod)%mod;
            }
            else
            {
                ans+=com(s-r+n-1,n-1);
                ans=(ans%mod+mod)%mod;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

Codeforces Round #258 (Div. 2)-(A,B,C,D,E)

时间: 2024-10-25 15:39:08

Codeforces Round #258 (Div. 2)-(A,B,C,D,E)的相关文章

Codeforces Round #258 (Div. 2)

A - Game With Sticks 题目的意思: n个水平条,m个竖直条,组成网格,每次删除交点所在的行和列,两个人轮流删除,直到最后没有交点为止,最后不能再删除的人将输掉 解题思路: 每次删除交点所在的行和列,则剩下n-1行和m-1列,直到行或列被删完为止,最多删除的次数为min(n,m),删除min(n,m)后剩余的都是行或者列(注意行与行,列与列之间不可能有交点).只需要判断min(n,m)的奇偶性. #include <iostream> #include <vector&

Codeforces Round #258 (Div. 2) B. Sort the Array(简单题)

题目链接:http://codeforces.com/contest/451/problem/B ---------------------------------------------------------------------------------------------------------------------------------------------------------- 欢迎光临天资小屋:http://user.qzone.qq.com/593830943/ma

Codeforces Round #258 (Div. 2) A. Game With Sticks(数学题)

题目链接:http://codeforces.com/contest/451/problem/A ---------------------------------------------------------------------------------------------------------------------------------------------------------- 欢迎光临天资小屋:http://user.qzone.qq.com/593830943/ma

Codeforces Round #258 (Div. 2) 小结

A. Game With Sticks (451A) 水题一道,事实上无论你选取哪一个交叉点,结果都是行数列数都减一,那如今就是谁先减到行.列有一个为0,那么谁就赢了.因为Akshat先选,因此假设行列中最小的一个为奇数,那么Akshat赢,否则Malvika赢. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

Codeforces Round #258 (Div. 2/A)/Codeforces451A_Game With Sticks

解题报告 http://blog.csdn.net/juncoder/article/details/38102263 n和m跟木棍相交,问一人取一交点(必须是交点,且取完后去掉交点的两根木棍),最后谁赢 思路: 取最大正方形,以对角线上的交点个数判断输赢. #include <iostream> #include <cstdio> using namespace std; int main() { int m,n; while(cin>>n>>m) { i

Codeforces Round #258 (Div. 2/C)/Codeforces451C_Predict Outcome of the Game(枚举)

解题报告 http://blog.csdn.net/juncoder/article/details/38102391 题意: n场比赛其中k场是没看过的,对于这k场比赛,a,b,c三队赢的场次的关系是a队与b队的绝对值差d1,b队和c队绝对值差d2,求是否能使三支球队的赢的场次相同. 思路: |B-A|=d1 |C-B|=d2 A+B+C=k 这样就有4种情况,分别是: B>A&&C<B B>A&&C>B B<A&&C<

Codeforces Round #258 (Div. 2)Devu and Flowers 容斥原理

题目:Codeforces Round #258 (Div. 2)Devu and Flowers 题意:n个boxes ,第i个box有fi个flowers,每个boxes中的flowers完全相同,不同boxes的flowers不同,求从n个boxes中取出s个flowers的方案数.n<=20,s<=1e14,fi<=1e12. 排列组合的题目,一解法可用容斥原理(inclusion exclusion principle) . 有2中写法dfs和集合.下为集合写法. #inclu

Codeforces Round #258 (Div. 2)[ABCD]

Codeforces Round #258 (Div. 2)[ABCD] ACM 题目地址:Codeforces Round #258 (Div. 2) A - Game With Sticks 题意: Akshat and Malvika两人玩一个游戏,横竖n,m根木棒排成#型,每次取走一个交点,交点相关的横竖两条木棒要去掉,Akshat先手,给出n,m问谁赢. 分析: 水题,很明显不管拿掉哪个点剩下的都是(n-1,m-1),最后状态是(0,x)或(x,0),也就是拿了min(n,m)-1次,

Codeforces Round #258 (Div. 2) B. Jzzhu and Sequences(矩阵快速幂)

题目链接:http://codeforces.com/problemset/problem/450/B ---------------------------------------------------------------------------------------------------------------------------------------------------------- 欢迎光临天资小屋:http://user.qzone.qq.com/593830943