Div2每天两题

特殊的正方形


输入nn,输出nn行nn列的由+.组成的正方形,其中最外面一圈全是+,第二圈全是.,...,对于第ii圈,如果ii是奇数,那么全是+,否则全是.

输入格式

一行,一个整数nn

输出格式

nn行,为满足题目要求的正方形。注意不要有行末空格。

样例输入
10
样例输出
++++++++++
+........+
+.++++++.+
+.+....+.+
+.+.++.+.+
+.+.++.+.+
+.+....+.+
+.++++++.+
+........+
++++++++++
数据范围

对于100%100%的数据,保证2≤n≤1002≤n≤100

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
char a[N][N];
int main()
{
     int n;cin>>n;
     for(int i=1;i<=ceil(n/2.0);i++)
     {
        for(int j=i;j<=n+1-i;j++)
        {
            if(i%2)
            {
            a[i][j]=a[n+1-i][j]=a[j][i]=a[j][n+1-i]='+';
            }
            else 
            {
            a[i][j]=a[n+1-i][j]=a[j][i]=a[j][n+1-i]='.';
            }
        }
     }    
    for(int i=1;i<=n;i++)
   {
        for(int j=1;j<=n;j++)
        cout<<a[i][j];
        cout<<endl;     
   }

     
    return 0;
}

走楼梯2


楼梯有 nn 阶,上楼可以一步上一阶,也可以一步上二阶。

但你不能连续三步都走两阶,计算走到第nn阶共有多少种不同的走法。

输入格式

一行,一个数字,表示nn

输出格式

输出走楼梯的方式总数。

样例输入
6
样例输出
12
数据规模

对于100%100%的数据,保证n≤50n≤50

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define endl '\n';
const int N = 60;
int f[N][3];
int main()
{
    int n, j = 0; cin >> n;
    //f[1][0] = 1, f[2][0] = 1, f[2][1] = 1, f[2][2] = 0, f[1][1] = 0, f[1][2] = 0;
    f[0][0]=1;
    for (int i = 0; i <= n; i++)
    {
        for (int j = 0; j <3; j++)
        {
            f[i + 1][0] += f[i][j];
            if (j < 2)f[i + 2][j + 1] += f[i][j];
        }
    }
    cout << f[n][0] + f[n][1] + f[n][2] ;
    return 0;
}

#460. 走路


有一条很长的数轴,一开始你在00的位置。接下来你要走nn步,第ii步你可以往右走aiai或者bibi。

nn步之后,00到mm的每个位置,能不能走到?

输入格式

第一行,两个整数n,mn,m。

接下来nn行,每行两个整数ai,biai,bi。

输出格式

一行,一共m+1m+1个数,每个数都是0或1表示能否走到,数字之间不用空格隔开。

输入样例

3 10
1 2
2 6
3 3

输出样例

00000011001
数据规模

对于所有数据,保证1≤n≤100,1≤m≤105,1≤ai,bi≤10001≤n≤100,1≤m≤105,1≤ai,bi≤1000。

如果最后一步走到了位置i,那么倒数第二步就需要走到i-a或者i-b,定义f[i][j]表示走了i步能否到达位置j,注意运算的时候用逻辑或,最后输出走了n步能到达的位置i,即f[n][i];
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+1005;
int n,m,f[110][N],a[105],b[105];
int main()
{
    cin>>n>>m;
    f[0][0]=1;
    for(int i=1;i<=n;i++)
    {
    cin>>a[i]>>b[i];
    if(a[i]>b[i])
    {
        int t = a[i];
        a[i]=b[i];
        b[i]=t; 
    }
}
    for(int i=1;i<=n;i++){
        for(int j=m;j>=a[i];j--){    
        f[i][j]|=f[i-1][j-a[i]];
        if(j>=b[i])
        f[i][j]|=f[i-1][j-b[i]];    
        }
    }
    for(int i=0;i<=m;i++)    
    {
    if(f[n][i]>0)
    cout<<'1';
    else cout<<'0';
}
    return 0;
}

#455. 简单分数统计


NN 个好朋友在codeforces上参加一场包含 MM 个题目的比赛, 比赛期间codeforces网站一共有 kk 次提交。

已知每个题目的分数,

但是由于他们只能查到在比赛期间codeforces总共的提交记录(其他用户提交的其他题目记录也包含在内, 即存在不属于该场比赛的题目),

所以想请你编写一个程序算出他们每个人的分数。

输入格式

第一行三个整数 NN, MM, KK 分别表示好朋友的个数, 题目的个数, 和提交的总次数(其中0<N,M,K<=2000<N,M,K<=200)。

接下来 NN 行 第 ii 行输入为第 ii 个人的id,

接下来 MM 行 第 jj 行输入为第 jj 个题目的名称和分数,

接下来 KK 行 第 kk 行输入为第 kk 次提交的提交者id, 题目名称和结果("WA" 或 "AC", 如果"AC"代表通过这个题目, 提交者获得对应分数)。

注: 题目名称和id均为仅包含英文字母和数字的字符串, 题目分数为小于等于 1e61e6 的正整数. 每一行的多个输入之间用空格隔开。

所有输入的字符串长度 lengthlength 满足 0<length≤5000<length≤500

所有用户id和题目名称不存在重名, 用户AC了某个题之后之后不会再重复提交该题, 好朋友们只会提交属于比赛的题目。

输出格式

输出 NN 行, 第 ii 行输出第 ii 个人的名字和对应分数 (名字和分数用空格隔开)。

样例输入
2 2 4
GabrielPessoa
beza
metebronca 100
geometry 200
beza metebronca AC
ffern numbertheory AC
GabrielPessoa geometry WA
beza geometry AC
样例输出
GabrielPessoa 0
beza 300
样例解释

beza 过了 metebronca和geometry 拿到 300300 分。

GabrielPessos 没有过题, 所以是 00 分。

还有一些其他选手提交的其他题目忽略不计。

#include<iostream>
#include<cstring>
#include<unordered_map>
using namespace std;
const int N = 205;
struct
{
    string id;
    int sco;
}pip[N];
unordered_map<string, int>item;
int n, m, k;
int main()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)cin >> pip[i].id;
    string nam; int num;
    for (int i = 1; i <= m; i++)
    {
        cin >> nam >> num;
        item.insert({ nam,num });
    }
    string a, b, c;
    for (int i = 1; i <= k; i++)
    {
        cin >> a >> b >> c;
        for (int j = 1; j <= n; j++)
        {
            if (a == pip[j].id && c == "AC")
                pip[j].sco += item[b];
        }
    }
    for (int i = 1; i <= n; i++)
    {
        cout << pip[i].id << ' ' << pip[i].sco << endl;
    }
    return 0;
}

#453. Alice的德州扑克


德州扑克是目前世界上最流行的扑克游戏,全世界有众多相关的比赛,例如是 WSOP,WPT,EPT等,也让这款游戏的玩法变得层出不穷,丰富多变。 不要被简单的游戏规则而误导,复杂多变的比赛状况,让这款游戏在高水平的竞技中会变得非常复杂,这也让人们为德州扑克给出了这样一句评价 ”用一刻就能学会,但要用一生才能掌握” 。

现在我们并不在乎游戏规则是什么,因为 Alice 是一个德州扑克高手,他对于德州扑克的规则烂熟于心,不过他每次都记不得牌型的大小关系,他知道你是一个编程高手,所以他想让你帮他写一个程序:输入五张牌的大小和花色,输出这五张牌能组成的最大牌型.你能帮帮他吗?

为了降低你的编程难度,我们规定:

  1. 输入的牌都是来源于同一副扑克牌

  1. 输入的牌的点数都是非递减的

  1. 所有花色没有大小之分

下面给出各牌型,(从大到小)

  1. 皇家同花顺(ROYAL FLUSH):五张顺连的牌(点数连续单调递增),且最大的一张牌是A(Ace),并且五张牌的花色相同

  1. 同花顺(STRAIGHT FLUSH):五张顺连的牌(点数连续单调递增),不规定最大的一张牌是A(Ace),并且五张牌的花色相同

  1. 四条(FOUR OF A KIND):至少四张牌的点数相同

  1. 葫芦(FULL HOUSE):至少三张牌的点数相同,并且除此之外还有两张牌的点数相同

  1. 同花(FLUSH):五张牌的花色都相同

  1. 顺子(STRAIGHT):五张顺连的牌(点数连续单调递增),不要求五张牌的花色相同

  1. 特别注意:由于 Alice 是个谨慎的人,所以比 三条(THREE OF A KIND) (包括三条) 小的牌型 Alice 不在乎他们的大小关系,你只需要告诉 Alice 弃牌就行

输入格式

输入两行,每行五个数字,第一行的第 ii 个字符表示第 ii 张扑克的点数,

第二行的第 ii 个数字表示第 ii 张扑克花色。(保证输入的牌的点数是非递减的,且所有输入均合法)

点数和对应输入的数字:

  • 2−102−10 对应 2 - 10

  • J(Jack)J(Jack) 对应 11

  • Q(Queen)Q(Queen) 对应 12

  • K(King)K(King) 对应 13

  • A(Ace)A(Ace) 对应 14

花色和对应输入的数字:

  • 黑桃 (Spades) 对应 1

  • 方片 (Diamonds) 对应 2

  • 红桃 (Hearts) 对应 3

  • 梅花 (Clubs) 对应 4

输出格式

输出这五张牌能组成的最大牌型。

  • 如果最大是皇家同花顺输出 "ROYAL FLUSH"

  • 如果最大是同花顺输出 "STRAIGHT FLUSH"

  • 如果最大是四条输出 "FOUR OF A KIND"

  • 如果最大是葫芦输出 "FULL HOUSE"

  • 如果最大是同花输出 "FLUSH"

  • 如果最大是顺子输出 "STRAIGHT"

  • 如果最大的牌型小于等于三条输出"FOLD",劝 Alice 弃牌

  • 输出不包括引号

样例输入1
10 11 12 13 14
1 1 1 1 1
样例输出1
ROYAL FLUSH
样例输入2
10 11 12 13 14
1 2 1 3 4
样例输出2
STRAIGHT
样例输入3
6 6 6 7 7
1 2 3 1 3
样例输出3
FULL HOUSE
样例输入4
3 3 6 6 9
1 2 1 2 1
样例输出4
FOLD
if语句判断即可,不过错一个测试点倒扣100分属实没想到
#include<iostream>
using namespace std;
int a[10],b[10],flag1=1,flag2=1,num,pos;//flag1标记顺子,flag2标记花色,num表示相等的牌的个数,pos标记牌型 
string s[10]={"FOLD","ROYAL FLUSH","STRAIGHT FLUSH","FOUR OF A KIND","FULL HOUSE","FLUSH","STRAIGHT"}; 
int main()
{
    for(int i=1;i<=5;i++)
    {
        cin>>a[i];
    }
    for(int i=1;i<=5;i++)
    {
        if(a[i]==a[3])num++;
        if(i<5){
        if(a[i+1]!=a[i]+1)flag1=0;
    }
    }
    if(num==3)
    {
        if(a[1]==a[2]||a[4]==a[5])pos=4;//葫芦 
    }
    if(num==4)
    pos = 3;//四条
    for(int i=1;i<=5;i++){
    cin>>b[i];
    int t = b[1];
    if(b[i]!=t)flag2=0;
}
     if(flag1){
     if(flag2){
      if(a[5]==14)     
      pos = 1;//皇家同花顺 
      else pos = 2;//同花顺 
}
       else pos = 6;//顺子 
}
    else  
    {
        if(flag2)
        pos = 5;//同花 
    }
    cout<<s[pos];
    return 0;
}

#465. 订单编号

小缘开了一家公司,生意很好,每天都会收到很多订单,自动交易系统会自动给这些订单生成没有重复的订单编号。但是有一天,系统出现了未知的错误,导致当天的订单编号可能有重复的,这可把小缘急坏了。你可以帮助小缘按照规则给这些订单重新编号吗?

按照时间先后顺序给出 NN 个正整数作为原订单编号,你需要按照规则依次赋予这些订单新的编号,对于任意一个订单,要找到大于等于其原订单编号且未被使用过的(没有被之前的订单作为新的订单编号)的最小整数,作为它的新订单编号。

例如: 原订单编号依次为1 2 3 1,则新订单编号应该为1 2 3 4 (前3个订单的原订单编号都没有使用过,所以用其原订单编号即可,对于第四个订单,原订单编号为1,而1, 2, 3都已经被使用过,所以新订单编号为4)。

输入格式

第一行输入一个整数 NN (1≤N≤5×105)(1≤N≤5×105)。

第二行输入 NN 个数 aiai (1≤ai≤109)(1≤ai≤109) 作为原订单编号。

输出格式

输出一行,包含 NN 个整数为新的订单编号。

样例输入1
6
2 3 4 1 1 1
样例输出1
2 3 4 1 5 6
样例输入2
3
1000000000 1000000000 1000000000
样例输出2
1000000000 1000000001 1000000002
样例输入3
6
4 5 1 2 1 1
样例输出3
4 5 1 2 3 6
数据被加强了捏,原来的修改数组用并查集维护可以过的,现在超内存了QAQ
#include <iostream>
#include <cstring>
#include <algorithm>
#include<set>
using namespace std;
int n;
set <pair<int,int> >c;
void insert(int l,int r)
{
    if(l>r)return ;
    c.insert(make_pair(r,l));
}
int main()
{
    scanf("%d",&n);
    c.insert(make_pair(2e9,1));
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        auto t = c.lower_bound(make_pair(x,0));
        if(t->second<=x)
        {
            printf("%d ",x);
            insert(t->second,x-1);
            insert(x+1,t->first);
            c.erase(t);
        }else
        {
            printf("%d ",t->second);
            insert(t->second+1,t->first);
            c.erase(t);
        }
    }
    return 0;
}

#463. 饿饿 饭饭


有nn个同学正在排队打饭,第ii个同学排在从前往后第ii个位置。但是这天食堂内只有一个食堂阿姨,为了使同学们都能尽快的吃上饭,每一个同学在打完一份饭之后就会排在队伍的末尾先吃着打到的饭,我们知道第ii个同学的饭量为aiai,也就是说第ii个同学要吃aiai份饭才能吃饱,当一位同学吃饱后,他就会立刻离开食堂,不会排在队伍的末尾。食堂阿姨想知道,在打完k份饭之后,队伍的样子是怎样的,但是食堂阿姨数学不太好,想让你帮忙想想办法。

输入格式

第一行给出两个整数nn,kk

第二行给出nn个整数a1,a2,......ana1,a2,......an

输出格式

如果食堂阿姨打饭数少于k,请输出"-1"。

否则按照队伍顺序输出每一个同学的编号。

样例输入1
3 3
1 2 1
样例输出1
2
样例输入2
4 10
3 3 2 1
样例输出2
-1
样例输入3
7 10
1 3 3 1 2 3 1
样例输出3
6 2 3
数据规模

数据保证1≤n≤105, 0≤k≤1014, 1≤ai≤1091≤n≤105, 0≤k≤1014, 1≤ai≤109

需要找到一共能够完整的轮流几次,最后在剩余的次数中进行分配,注意队列先进先出的特性即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
typedef long long ll;
using namespace std;
const int N = 1e5 + 10;
ll k, s;
int n, a[N], b[N], ans, j;
ll check(int m)
{
    ll res = 0;
    for (int i = 1; i <= n; i++)
    {
        if (a[i] <= m)
            res += a[i];
        else res += m;
    }
    return res;
}
int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        s += a[i];
    }
    if (s < k) {
        cout << -1 << endl;
        return 0;
    }
    int l = 0, r = 1e9;
    while (l <= r)
    {
        int mid = (l + r) / 2;
        if (check(mid) <= k)
            ans = mid, l = mid + 1;
        else r = mid - 1;
    }
    k -= check(ans);//ans轮过后还剩下多少份饭 
    for (int i = 1; i <= n; i++)
    {
        if (a[i] > ans)
            b[++j] = i;
    }//一共有j位同学在ans轮过后还在队里面
    for (int i = k + 1; i <= j; i++)//(第K+1到j位同学不用考虑剩下饭的分配,直接在最前面输出)
    {
        cout << b[i] << ' ';
    }
    for (int i = 1; i <= k; i++)//第1到j位同学在第ans+1轮分配后如果饭量为0,出队
    {
        if (a[b[i]] > (ans + 1))//b[i]存的是编号!!作为下边索引
            cout << b[i] << ' ';
    }
    return 0;
}

#461. 任务分配


你有nn个任务,其中第ii个任务,在sisi开始,eiei时刻结束,如果做这个任务,你能获得wiwi的收益。

但是你在一个时刻只能做一个任务,问选择哪些任务,能让你的收益尽量大。

注意:你在上一个任务结束后马上开始下一个任务是可以的。

输入格式

第一行一个整数nn。

接下来nn行,每行三个整数si,ei,wisi,ei,wi。

输出格式

一个数,表示答案。

样例输入

3
1 3 100
2 4 199
3 5 100

样例输出

200
数据规模

对于所有数据,保证1≤n≤103,1≤si<ei≤103,1≤wi≤1051≤n≤103,1≤si<ei≤103,1≤wi≤105。

这是一个经典的贪心问题,我们可以按照任务结束时间从小到大排序,然后依次选择结束时间最早且收益最大的任务。具体实现可以使用 STL 中的 sort 函数。
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1010;

struct Task {
int s, e, w;
} task[N];

bool cmp(Task a, Task b) {
return a.e < b.e;
}

int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> task[i].s >> task[i].e >> task[i].w;
}
sort(task, task + n, cmp);
int dp[N] = {0};
for (int i = 0; i < n; i++) {
for (int j = i - 1; j >= 0; j--) {
if (task[j].e <= task[i].s) {
dp[i] = max(dp[i], dp[j]);
}
}
dp[i] += task[i].w;
}
int res = 0;
for (int i = 0; i < n; i++) {
res = max(res, dp[i]);
}
cout << res << endl;
return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值