Codeforences #297 div2 (A,B,C,D,E)

来源:互联网 发布:数学软件有哪些 编辑:程序博客网 时间:2024/05/16 16:20

【A题目链接】点击打开链接

【题意】给了一个数n,和2*n-2个字符组成的字符串,其中奇数位置的字符是小写,偶数为大写。如果小写字符和大写字符是匹配的,那么就可以成功开门,问你要从1走到n,至少需要带多少把钥匙才能顺利开门。

【解题思路】贪心即可。把走到当前位置没用到的钥匙用一个数组hash下来然后判断一下即可。

【AC代码】

#include <bits/stdc++.h>using namespace std;const int maxn = 200010;int key[200];int n;char s[maxn];int main(){    cin>>n;    cin>>s;    memset(key,0,sizeof(key));    int cnt=0;    for(int i=0; i<(int)strlen(s); i+=2)    {        if(s[i+1]+32==s[i])        {            cnt++;        }        else        {            key[s[i]-32]++;            if(key[s[i+1]]>0)            {                cnt++;                key[s[i+1]]--;            }        }    }    cout<<n-1-cnt<<endl;    return 0;}

【B题目链接】点击打开链接

【解题思路】由于是对称的反转,所以暴力统计前一半的反转次数就可以了。

【AC代码】

#include <bits/stdc++.h>using namespace std;#define ll long longconst int maxn=200010;const int maxm=100010;char s[maxn];int a[maxn];ll cnt[maxn];int m;int main(){    scanf("%s",s+1);    int len=strlen(s+1);    cin>>m;    for(int i=1; i<=m; i++)    {        cin>>a[i];        cnt[a[i]]++;    }    for(int i=1; i<=len/2; i++)    {        cnt[i]+=cnt[i-1];    }    for(int i=1; i<=len/2; i++)    {        if(cnt[i]%2==1)        {            swap(s[i],s[len-i+1]);        }    }    printf("%s",s+1);    return 0;}

【C题目链接】点击打开链接

【解题思路】给了n个木棍,并且有每一根木棍的长度,要我们找到一个最大的矩形让它的面积足最大,并且满足每根木棍的长度可以减去1。排序后贪心找最大的匹配 木棍对即可。

【AC代码】

#include <bits/stdc++.h>using namespace std;#define ll long longconst int maxn=100005;int a[maxn];ll ans,x;int n;int main(){    cin>>n;    for(int i=1; i<=n; i++)    {        cin>>a[i];    }    x=0;    sort(a+1,a+n+1);    for(int i=n-1; i>=1; i--)    {        if(a[i+1]-a[i]<2)        {            if(x) ans+=(ll)a[i]*x,x=0;            else x=a[i];            i--;        }    }    cout<<ans<<endl;    return 0;}

【D题目链接】点击打开链接

【题意】给了一个n*m的迷宫,迷宫里面有空地用.表示,有墙用*表示,要你去掉一些墙使得最后的联通的空地都是矩形,并且要保证去掉的墙的个数最小。

【解题思路】观察样例,可以猜测具有. . . *这种形式的2*2的小迷宫都会变成. . . .,所以直接找这种形式的小迷宫,进行BFS就行了,这是贪心加BFS的应用。

【AC代码】

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int n,m;char maze[2010][2010];int dir[8][2]={{0,1},{0,-1},{-1,0},{1,0},{1,1},{1,-1},{-1,1},{-1,-1}};int vis[2010][2010];queue<pair<int,int> >que;int judge(int i,int j){    if(maze[i][j]=='.'||i<0||i>n-1||j<0||j>m-1) return false;    if(maze[i][j+1]=='.'&&maze[i+1][j]=='.'&&maze[i+1][j+1]=='.') return true;    if(maze[i][j-1]=='.'&&maze[i+1][j-1]=='.'&&maze[i+1][j]=='.') return true;    if(maze[i-1][j]=='.'&&maze[i-1][j+1]=='.'&&maze[i][j+1]=='.') return true;    if(maze[i][j-1]=='.'&&maze[i-1][j-1]=='.'&&maze[i-1][j]=='.') return true;    return false;}void BFS(){    while(!que.empty())    {        int x=que.front().first;        int y=que.front().second;        que.pop();        maze[x][y]='.';        for(int i=0; i<8; i++)        {            int tx=x+dir[i][0];            int ty=y+dir[i][1];            if(judge(tx,ty)&&!vis[tx][ty])            {                vis[tx][ty]=true;                que.push(make_pair(tx,ty));            }        }    }}int main(){    cin>>n>>m;    for(int i=0; i<n; i++) scanf("%s",maze[i]);    memset(vis,false,sizeof(vis));    for(int i=0; i<n; i++)    {        for(int j=0; j<m; j++)        {            if(judge(i,j))            {                que.push(make_pair(i,j));                vis[i][j]=true;            }        }    }    BFS();    for(int i=0; i<n; i++)    {        printf("%s\n",maze[i]);    }    return 0;}

【E题目链接】点击打开链接

【题意】给了n个数,然后你可以改变n个数里面的k个数,使这k个数变成这个数的阶乘,问你有多少种方式能够使得这这些数的和等于s。

【解题思路】由于n最大为25个,每个数有不选,不变,变本身的阶乘3种情况,所以一共有3^25种情况,直接枚举肯定T。所以考虑另外一种做法,我们可以先算前n/2个数然后用map存储下来,再算后n/2个数,在后n/2个数中算出来的数架设为sum2如果s-sum2在前n/2个数的和中出现过,则我们找到相应个数的解,这样将复杂度降到2 * 3^12 约等于1e6的数量级,注意s的范围是10^16,而18! = 6*10^15因此18以后的阶乘我们都不用去算了,搜索的时候当然也不用搜。

【AC代码】

#include <map>#include <cstdio>#include <cstring>#include <iostream>using namespace std;#define ll long longll fac[20]={1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880,3628800, 39916800, 479001600, 6227020800 ,87178291200 ,1307674368000,20922789888000 ,355687428096000 ,6402373705728000};int n,k;ll a[30],s,ans;map<ll,ll>mp[30];void dfs1(int i,ll cnt,ll sum){    if(sum>s||cnt>k) return;    if(i==n/2)    {        mp[cnt][sum]++;        return ;    }    dfs1(i+1,cnt,sum);    dfs1(i+1,cnt,sum+a[i]);    if(a[i]<=18) dfs1(i+1,cnt+1,sum+fac[a[i]]);}void dfs2(int i,ll cnt,ll sum){    if(sum>s||cnt>k) return ;    if(i==n)    {        for(int j=0; j+cnt<=k; j++)        {            if(mp[j].count(s-sum))                ans+=mp[j][s-sum];        }        return ;    }    dfs2(i+1,cnt,sum);    dfs2(i+1,cnt,sum+a[i]);    if(a[i]<=18)    {        dfs2(i+1,cnt+1,sum+fac[a[i]]);    }}int main(){    ans=0;    cin>>n>>k>>s;    for(int i=0; i<n; i++) cin>>a[i];    dfs1(0,0,0);    dfs2(n/2,0,0);    cout<<ans<<endl;    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 cd光盘读不出来怎么办 最近脸干的不行怎么办 脸感觉干的不行怎么办 新生儿睡觉黑白颠倒了怎么办 婴儿吐水和奶花怎么办 刚刚出生的宝宝拉肚子怎么办 刚出生的婴儿拉肚子怎么办 新生儿5天拉稀水怎么办 10个月孩子拉肚子怎么办 不满月的宝宝拉肚子怎么办 一周岁宝宝发烧腹泻呕吐怎么办 6个月宝宝37度怎么办 1岁宝宝发烧37.2怎么办 新生儿发烧37度3怎么办 两个月宝宝抵抗力差怎么办 6月宝宝着凉拉稀怎么办 六个月的宝宝拉肚子怎么办 衣服颜色太深了怎么办 一多半宝宝爱喝水不爱吃饭怎么办 十个月宝宝不爱吃饭怎么办 十个月宝宝突然不爱吃饭怎么办 二十个月宝宝不爱吃饭怎么办 十个月的宝宝不爱吃饭怎么办 6年级学生数学差怎么办 打印机打不出来就是一张白纸怎么办 wps表格下拉数字不递增怎么办 wps表格圈怎么打出来怎么办 手表固定圈掉了怎么办 起来觉得头晕头胀怎么办? 孩子不好好写作业怎么办 孩子考试考差了怎么办 孩子计算题马虎大意怎么办 二年级孩子不认字怎么办 发现计算上的错误怎么办 孩子不好好做作业怎么办 手破了红肿了怎么办呢 老师反应孩子在校粗心胆小怎么办 四年级的学生计算粗心怎么办 老打孩子骂孩子怎么办 站久了脚肿了怎么办 孩子初中了书写越来越潦草怎么办