ccf刷题记终级版01

43 篇文章 0 订阅
30 篇文章 0 订阅

不知不觉间,大学已经过去了一大半了,acm生涯也随着乌鲁木齐之行的谢幕而逐渐进入了暮年,多么希望自己再年轻一年就好了。

这一年来,平心而论确实可能为了丰富的大学生活而并没有太过于重视训练,涉猎过广,满满的经历导致了精力的分散,不过也算还可以吧,有了不少提升了,本可以有更好成绩的,感觉还是有些地方存在很大空间,但毕竟存在取舍

那么,就让明年的ccf以及cccc,省赛这些谢幕曲不留遗憾,完成未完成的奋斗生涯。

由于之前的ccf刷题记感觉很好,于是决定在之前的基础上推出2.0终极版,以提高自己的能力,继续自己的acm生涯,使自己在接下来的acm生涯末期不留遗憾。


说来也巧,今天正是距我上一次考ccf出成绩刚好一周年的日子,想想去年的自己还无所事事,到处浪荡,做了两题甚至还做睡着了,不过经过一年的时间从弱鸡选手成长为icpc区域赛选手也还算有较大进步的。




刷题ing


ccf的第一套题,感觉难度还是不大的,2h45min成功ak,第一次ak ccf的一整场比赛。以一场ak里程碑来庆祝一周年纪念日,感觉还是蛮不错的

同样是四年前这个时间的老题了,题型感觉和现在完全不一样

201312-1 出现次数最多的数

a题一如既往的水题,瞬间秒切


思路:由于数据范围很小,那么就利用类似于桶排的思想,强行模拟一遍就好了

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 1e4+10;

int s[maxn];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(s,0,sizeof s);
        while(n--)
        {
            int temp;
            scanf("%d",&temp);
            s[temp]++;
        }
        int maxt = 0;
        int id = 0;
        for(int i=1;i<=10000;i++)
        {
            if(s[i]>maxt)
            {
                maxt = s[i];
                id = i;
            }
        }
        printf("%d\n",id);
    }
    return 0;
}

201312-2 ISBN号码

b题就现在的b题来说,难度还是不大的,依旧是数组字符串处理问题,但是还是在读取上出了点小问题,34min,成功ac,不过这速度就有点慢了


思路:由于取模具有交换性,那么当然还是强行模拟咯。数字字符的读取与处理问题,还是%c,%d,%1d的灵活运用与转换,最后注意一下括号的位置啊,一点点小错误就能debug很长时间的

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 1e5+10;

char isbn[10];

int main()
{
    scanf("%c",&isbn[0]);
    int sum = isbn[0] - '0';
    for(int pos = 1;pos<9;pos++)
    {
        scanf("%c",&isbn[pos]);
        if(isbn[pos] == '-')
        {
            pos--;
        }
        else
        {
            sum = (sum + (int)(isbn[pos]-'0') * (pos+1) )% 11;
        }
        //cout << isbn[i] << "*" << endl;
    }
    scanf("%c%c",&isbn[9],&isbn[9]);
    //cout << re << "*" << endl;
    bool rig = false;
    if(sum == 10)
    {
        if(isbn[9] == 'X')
        {
            rig = true;
        }
        else
        {
            isbn[9] = 'X';
        }
    }
    else
    {
        if(sum == (int)(isbn[9] - '0'))
        {
            rig = true;
        }
        else
        {
            isbn[9] = sum + '0';
        }
    }
    //cout << "***" << endl;
    if(rig)
    {
        //cout << "*" << endl;
        printf("Right\n");
    }
    else
    {
        //cout << "**" << endl;
        printf("%c-%c%c%c-%c%c%c%c%c-%c\n",isbn[0],isbn[1],isbn[2],isbn[3],isbn[4],isbn[5],isbn[6],isbn[7],isbn[8],isbn[9]);
    }
    return 0;
}

201312-3 最大的矩形

c题就和原来完全不一样了,当时的这题还是递推dp题,现在已经被经典的大模拟所替代了,递推想明白就比大模拟好写多了,感觉我做这类递推还是比较有心得的,14min成功ac


思路:看了一眼数据范围,支持n方算法,那么当然直接区间暴力,先预处理区间最小值,再枚举区间找最大值就好了,这题很清晰,就喜欢这种题目

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 1e3+10;

int maxh[maxn][maxn];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int h;
        int maxa = 0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&h);
            maxh[i][i] = h;
            maxa = max(maxa,h);
            for(int j=0;j<i;j++)
            {
                maxh[j][i] = min(maxh[j][i-1],h);
                maxa = max(maxa,maxh[j][i] * (i-j+1));
            }
        }
        printf("%d\n",maxa);
    }
    return 0;
}

201312-4 有趣的数

d题与现在的图论题也完全不一样了,这题倒是个数学题,数学题刚好也是我擅长的,24min ac


思路:这题本想着模拟的,一看取模,那肯定是不行了。

于是又想到打表找规律,以及生产算法的构造,发现似乎也都不怎么行,最终定位为数学题

感觉现在对暴力+一个算法的套路已经有了一定的认识了,记得之前经常卡在这种题上

不难发现,0、1可以归为一类,2、3可以归为一类,而且首元素一定是2,于是只要暴力枚举0、1组元素数量k,对长为n,k个0、1元素的组合共有C(n-1,k)种,最后两组内分别统计,结果相乘即可,最后就是对于组合数的计算,由于直接用公式存在除,对模问题需要求个逆元,比较麻烦,根据数据范围,直接n方递推杨辉三角即可

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 1010;

const long long mod = 1000000007LL;

long long comb[maxn][maxn];

void initial(int n)
{
    comb[0][0] = 1;
    for(int i=1;i<n;i++)
    {
        comb[i][0] = 1LL;
        //cout << comb[i][0] << " ";
        comb[i][i] = 1LL;
        for(int j=1;j<i;j++)
        {
            comb[i][j] = comb[i-1][j-1] + comb[i-1][j] % mod;
            //cout << comb[i][j] << " ";
        }
        //cout << comb[i][i] << endl;
    }
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        initial(n);
        long long sum = 0;
        for(long long k=2;k<=n-2;k++)
        {
            sum = (sum + (comb[n-1][k] * (k-1) % mod) * (n-k-1) % mod) % mod;
        }
        printf("%lld\n",sum);
    }
    return 0;
}

201312-5 I’m stuck!

e题的图论感觉有点类似现在d题的位置,dfs还是比较明显的,48min完成代码编写,然而感觉不知是自己太久没写代码了,还是自己代码示例太弱了,卡在字母使用上,又过了30min才成功过样例1wa,毫无疑问被卡掉了,最后在进行3min小细节修改以及11min分号查错,终于完成ak大业

e题总用时1h32min,整场总用时2h44min,最后一题用了一大半时间,不过总的结果还是可喜可贺的


思路:明显的dfs,从起点正向暴搜减去从终点逆向暴搜,分成dfs以及可达性判断两部分,思路很明确,但代码实现确实捉急啊,最后,考虑结果特殊情况

1.终点不一定会停止,可能继续前进

2.起点和终点的作用都可以等同为‘+’,四面可通可达

3.stuck条件为被困在起点,而不是无满足条件点

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 55;

char m[maxn][maxn];
bool vis[maxn][maxn];
bool cm[maxn][maxn];
int tcheck[maxn][maxn];

int r,c;

int t = 0;
/*
void prin()
{
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            cout << cm[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;
}
*/
bool movup(int x,int y)
{
    if(x<1||x>=r||y<0||y>=c)
        return false;
    if((m[x][y] == '+') || (m[x][y] == '|') || (m[x][y] == 'S') || (m[x][y] == 'T'))
        return true;
    else
        return false;
}

bool movdown(int x,int y)
{
    if(x<0||x>=r-1||y<0||y>=c)
        return false;
    if((m[x][y] == '+') || (m[x][y] == '|') || (m[x][y] == '.') || (m[x][y] == 'S') || (m[x][y] == 'T'))
        return true;
    else
        return false;
}

bool movlef(int x,int y)
{
    if(x<0||x>=r||y<1||y>=c)
        return false;
    if((m[x][y] == '+') || (m[x][y] == '-') || (m[x][y] == 'S') || (m[x][y] == 'T'))
        return true;
    else
        return false;
}

bool movrig(int x,int y)
{
    if(x<0||x>=r||y<0||y>=c-1)
        return false;
    if((m[x][y] == '+') || (m[x][y] == '-') || (m[x][y] == 'S') || (m[x][y] == 'T'))
        return true;
    else
        return false;
}

void dfs(int x,int y,bool d)
{
    //cout << "*" << d << endl;
    if(!vis[x][y])
        return ;
    vis[x][y] = false;
    //cout << "*" << endl;
    if(d)
    {
        //cout << m[x][y] << endl;
        if(m[x][y] == '#')
        {
            return ;
        }
        //cout << "#" << endl;
        cm[x][y] = true;
        if(movup(x,y))
            dfs(x-1,y,d);
        if(movdown(x,y))
            dfs(x+1,y,d);
        if(movlef(x,y))
            dfs(x,y-1,d);
        if(movrig(x,y))
            dfs(x,y+1,d);
        return ;
        //prin();
    }
    else
    {
        //cout << "#*" << endl;
        if(m[x][y] == '#')
        {
            return ;
        }
        cm[x][y] = false;
        //cout << x << " " << y << " " << m[x][y] << t << endl;
        //tcheck[x][y] = t++;
        //cout << "*#" << endl;
        if(movdown(x-1,y))
            dfs(x-1,y,d);
        if(movup(x+1,y))
            dfs(x+1,y,d);
        if(movrig(x,y-1))
            dfs(x,y-1,d);
        if(movlef(x,y+1))
            dfs(x,y+1,d);
        return ;
    }
}

int main()
{
    int str,stc,enr,enc;
    scanf("%d%d",&r,&c);
    memset(cm,false,sizeof(cm));
    for(int i=0;i<r;i++)
    {
        getchar();
        for(int j=0;j<c;j++)
        {
            scanf("%c",&m[i][j]);
            //cout << m[r][c] << "+++" << endl;
            if(m[i][j] == 'S')
            {
                str = i;
                stc = j;
            }
            else if(m[i][j] == 'T')
            {
                enr = i;
                enc = j;
            }
        }
        //cout << m[r][0] << "++" << endl;
    }
    //cout <<m[0][0] << "--" << endl;
    //prin();
    int sum1 = 0;
    memset(vis,true,sizeof(vis));
    dfs(str,stc,true);
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            if(cm[i][j])
            {
                sum1++;
            }
        }
    }
    //prin();
    memset(vis,true,sizeof(vis));
    dfs(enr,enc,false);
    //prin();
    int sum = 0;
    cm[str][stc] = false;
    cm[enr][enc] = false;
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            if(cm[i][j])
            {
                sum++;
            }
        }
    }
    if(sum1 == 1)
    {
        printf("I'm stuck!\n");
    }
    else
    {
        printf("%d\n",sum);
    }
    return 0;
}

文章地址:http://blog.csdn.net/owen_q/article/details/78836466

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值