CF练习赛130719 - from lanshui_Yang

来源:互联网 发布:阿富汗知乎 编辑:程序博客网 时间:2024/04/29 13:47

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] ; // 注意:以下数组应开大一些,因为                            //题目中要进行的操作会比较多,否则会WAint 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 ;}


原创粉丝点击