CF练习赛130719 - from lanshui_Yang

A.Flipping Game

       题目大意:输入一个数n , 然后输入n个数a1 , a2...an (ai = 0 或者 ai = 1 ,1 <=  i  <=  n) ,接下来你需要进行一个操作:选定两个下标i 和 j ,使ai , ai + 1 ......aj  按如下规则变化:ak = 1 - ak  (i <= k <= j)。要求经过这一步操作后,使这n个数中 1 的个数最多, 并输出这个最大值。此题,我原本以为是动态规划,就先做了后面的题,后来被队友告知直接暴力就可以,汗。。请看代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std ;
int s[105] ;
int s2[105] ;
int main()
{
    int n ;
    while (scanf("%d" , &n) != EOF)
    {
        int i , j ;
        for(i = 0 ; i < n ; i ++)
        {
            scanf("%d" , &s[i]) ;
        }
        int max = -1 ;
        for(i = 0 ; i < n ; i ++)
        {
            for(j = i ; j < n ; j ++)
            {
                for(int j3 = 0 ; j3 < n ; j3 ++)  // 别忘每次都要初始化
                {
                    s2[j3] = s[j3] ;
                }
                int k ;
                for(k = i ; k <= j ; k ++)
                    s2[k] = 1 - s2[k] ;
                int sum = 0 ;
                for(int j2 = 0 ; j2 < n ; j2 ++)
                {
                    if(s2[j2] == 1)
                        sum ++ ;
                }
                if(sum > max)
                {
                    max = sum ;
                }
            }
        }
        printf("%d\n" , max) ;
    }
    return 0 ;
}


B.Hungry Sequence

       题目大意:给你一个数n , 让你找出n 个数a1 , a2 ... an , 它们满足如下条件:a1 < a2 < a3 < ... < an , 并且对于任意的ai 和 aj (ai < aj), aj不能被ai 整除。任意一种满足条件的序列都可以。此题先用筛一下素数,然后,显然不同素数之间都是互质的,只要从小到大依次输出n个素数即可。请看代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std ;
const int MAXN = 10000008 ;
int s[MAXN] ;
int n ;
void prim()  // 建立素数表
{
    int i ;
    s[0] = s[1] = 1 ;
    for(i = 2 ; i <= MAXN ; i ++)
    {
        int j ;
        if(s[i] == 0)
            for(j = 2 ; j * i <= MAXN ; j ++)
            {
                s[i * j] = 1 ;
            }
    }
}
int main()
{
    memset(s , 0 , sizeof(s)) ;
    prim() ;
    while (scanf("%d" , & n) != EOF)
    {
        int i ;
        int j = 0 ;
        for(i = 2 ; ;)
        {
            if(s[i] == 0)
            {
                printf("%d" , i) ;
                j ++ ;
                if( j < n )
                {
                    printf(" ") ;
                }
            }
            i ++ ;
            if(j == n )
            {
                printf("\n") ;
                break ;
            }
        }
    }
    return 0 ;
}


C.Magic Five

       这道题是一道找规律推公式的题,唯一的难度在于用到数论中的欧拉定理和求一个数a mod n 的乘法逆元,但是这个我现在还不能掌握,准备日后等真正理解了再好好写一写此题的结题报告。原本这个题在BNU上我用简单的方法A掉了,但在CF上确实超时,可能是BNU 的问题吧,下面先写一下我原先的代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std ;
const int MAXN = 1e9 + 7;
const int M = 1e6 + 5 ;
char s[M] ;
long long sum[M] ;
long long mi(long long n)  //快速幂
{
    if(n == 0)
    return 1 ;
    if(n == 1)
    return 2 ;
    if(n % 2 == 0)
    return ((mi(n / 2) % MAXN) * (mi(n / 2) % MAXN)) % MAXN ;
    else
    return (((mi(n / 2) % MAXN) * (mi(n / 2) % MAXN)) * 2 ) % MAXN ;
}
int main()
{
    memset(s , 0 , sizeof(s)) ;
    memset(sum , 0 ,sizeof(sum)) ;
    while (scanf("%s" , s) != EOF)
    {
        int k ;
        scanf("%d" , &k) ;
        int len = strlen(s) ;
        int i ;
        int cnt = 0 ;
        for(i = 0 ; i < len ; i ++)
        {
            if(s[i] == '5' || s[i] == '0')
            {
                sum[cnt] = i ;
                cnt ++ ;
            }
        }
        long long ans = 0 ;
        int j ;
        for(i = 0 ; i < cnt ; i ++)
        {
            for(j = 0 ; j < k ; j ++)
            {
                ans = (ans + (mi((sum[i] + len * j)) % MAXN )) % MAXN ;
            }
        }
        printf("%lld" , ans) ;
    }
    return 0 ;
}


D.Block Tower

       题目大意:给你一个n * m 的矩形地图,地图中总共可能有两种符号:  ‘.’  和 ‘#’ ,‘.’ 表示空地, 能在这里建造房子,‘#’表示黑洞,不能在这里建造房子。能建造的房子共有两种:第一种是蓝色的房子,能容纳100 个 人 ;第二种是红色房子 , 能容纳200人,但是必须在蓝色房子旁边的空地才能建造。你能进行三种操作:一、建造蓝色房子 ,代号为“B”;二、建造红色房子,代号为“R”;三、摧毁建造的房子 ,代号为“D” 。现要求你在空地上建造房子,是能够容纳的人数最大,并输出你进行的操作的总步数和每步操作之行的内容,如:B 1 2  ,代表在点(1,2) 上建造蓝色房子。

      解题思路:此题采用dfs , 找出相邻的‘.’所占的最大区域(与寻找魔方的最大色块有些相似) ,并在此过程中将所有符号为 ‘.’ 的点都建上蓝色的房子,当搜索进行完时 ,便进入回退的过程中,并在此过程中将所有的点(除搜索的其实点外)上面的蓝色房子摧毁,然后再建上红色的房子,这样当回退结束后,原先相邻的符号为 ‘.’ 的区域中除搜索的起始点是蓝色房子外,其他的点均为红色房子,这样就能使所容纳的人数最大,因为红色的房子必须在蓝色房子的旁边建造,所以一块相邻的符号为 ‘.’ 的区域中不可能将所有的点都建为红色房子 。下面请看代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std ;
const int MAXN = 605 ;
char map[MAXN][MAXN] ;
int vis[MAXN][MAXN] ;
int n , m ;
int X[4] = {0 , 0 , 1 , -1} ;
int Y[4] = {1 , -1 , 0 , 0} ;
char clo[MAXN * MAXN * 10] ; // 注意:以下数组应开大一些,因为
                            //题目中要进行的操作会比较多,否则会WA
int zx[MAXN * MAXN * 10] ;
int zy[MAXN * MAXN * 10] ;
int cango(int x , int y)
{
    if( x >= 1 && x <= n && y >= 1 && y <= m && !vis[x][y] && map[x][y] == '.')
        return 1 ;
    return 0 ;
}
int cnt ;// 统计操作的步数
void dfs(int x , int y )  // 深搜
{
    vis[x][y] = 1 ;
    clo[cnt] = 'B' ;  // 对于深搜到的每个点先建上蓝色房子
    zx[cnt] = x ;  // 记录当前位置坐标
    zy[cnt] = y ;
    cnt ++ ;
    int k ;
    for(k = 0 ; k < 4 ; k ++)
    {
        int tx = x + X[k] ;
        int ty = y + Y[k] ;
        if(cango(tx , ty))
        {
            vis[tx][ty] = 1 ;
            dfs(tx , ty) ;
            clo[cnt] = 'D' ; // 深搜回退时遇到这个点,先把
                            //原先建的蓝色房子摧毁,然后再建造红色房子
            zx[cnt] = tx ;
            zy[cnt] = ty ;
            cnt ++ ;
            clo[cnt] = 'R' ;
            zx[cnt] = tx ;
            zy[cnt] = ty ;
            cnt ++ ;
        }
    }
}
int main()
{
    while (scanf("%d%d" , &n , &m) != EOF)
    {
        memset(map , 0 , sizeof(map)) ;
        memset(vis , 0 , sizeof(vis)) ;
        memset(clo , 0 , sizeof(clo)) ;
        memset(zx , 0 , sizeof(zx)) ;
        memset(zy , 0 , sizeof(zy)) ;
        int i , j ;
        cnt = 0 ;
        for(i = 1 ; i <= n ; i ++)
        {
            for(j = 1 ; j <= m ; j ++)
            {
                cin >> map[i][j] ;
            }
        }
        for(i = 1 ; i <= n ; i ++)
        {
            for(j = 1 ; j <= m ; j ++)
            {
                if(map[i][j] == '.' && !vis[i][j])
                {
                    dfs(i , j) ;
                }
            }
        }
        printf("%d\n" , cnt) ;
        for(i = 0 ; i < cnt ; i ++)
        {
            printf("%c %d %d\n" , clo[i] , zx[i] , zy[i]) ;
        }
    }
    return 0 ;
}


你可能感兴趣的:(CF练习赛130719 - from lanshui_Yang)