牛客小白月赛44

A.深渊水妖

题意:找到所有极长的不严格上升段,并找出它们当中右端点权值 - 左端点权值最大的那些个段,输出端点坐标。

绷不住啦,比赛时没有看明白题目wa了呜呜┭┮﹏┭┮

思路:最上上升子序列模型,双指针,找出区间两点最大的权值,然后在遍历一遍输出满足要求的区间左右端点值。

代码:

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10;
int n,a[N];

void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)    cin>>a[i];
    int maxn=0;
    for(int i=1;i<=n;i++){
        int j=i;
        while(j+1<=n&&a[j+1]>=a[j]) j++;
        maxn=max(maxn,a[j]-a[i]);
        i=j;
    }
    
    for(int i=1;i<=n;i++){
        int j=i;
        while(j+1<=n&&a[j+1]>=a[j]) j++;
        if(a[j]-a[i]==maxn) cout<<i<<' '<<j<<' ';
        i=j;
    }
    cout<<endl;
}

int main()
{
    int _;
    cin>>_;
    while(_--){
        solve();
    }
    return 0;
}

B.顽皮恶魔

题意:

你的庄园是一块 n×m的草坪。

现在有一些格子是普通植物 P,有一些格子是萝卜保护伞 ∗,有一些格子是僵尸 Z。(已经在格子上的僵尸不会吃掉植物或移动)

tip:萝卜保护伞可以保护周围 3×3 的植物,即一个位于位置 (x,y)(x,y)(x,y) 的萝卜保护伞可以保护位于 (x±1,y),(x,y±1),(x±1,y±1)以及自身九个格子上的植物。

现在你想知道,对于这样一块给定的草坪,假设有无穷多个飞贼,能够偷走最多数量的植物是多少。

思路:枚举每个点,找到没有被萝卜保护伞保护的植物即可。ps:每次清空数组不能用memset(g,0,sizeof(g)),会导致TLE,因为这个T了好几次,难顶。

代码:

#include<bits/stdc++.h>

#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define INF 0x3f3f3f3f
using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;

const int N=1e3+10;
int n,m;
int t;
int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};

int main()
{
    cin>>t;
    while(t--)
    {
        char  g[N][N];
        int ans=0;
        cin>>n>>m;
        for(int i=0;i<=n+1;i++)
            for(int j=0;j<=m+1;j++)
                g[i][j]='Z';
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>g[i][j];
                if(g[i][j]=='P')
                    ans++;
            }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(g[i][j]=='*')
                {
                    for(int k=0;k<8;k++)
                    {
                        int x=i+dx[k],y=j+dy[k];
                        if(g[x][y]=='P'){
                            ans--;
                            g[x][y]='Z';
                        }
                    }
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

C.绝命沙虫

题意:

初始时你的手上有 NNN 元 RMB。

交易规则如下:

\[你通过充值 a 元可以获得 a×100红点和min⁡{10000,a×100×(M−1)}绿点,其中 M 是充值返点倍率。 \]

\[你每次充值的数量必须是正整数,也就是说不能为零或负数。 \]

\[你通过出售 b红点可以获得 \left\lfloor\frac{b}{200}\right\rfloor 元RMB 和 \left\lfloor\frac{b}{10}\right\rfloor 点消费经验。 \]

\[你通过出售 c绿点可以获得 \left\lfloor\frac{c}{10}\right\rfloor 点消费经验。 \]

给定 N,M,请回答你最后获得的消费经验是多少。

思路:按照给定规则进行模拟即可,需要注意到精度问题,比赛时粗心看到一位小数就没有考虑精度被卡QwQ.

代码:

#include<bits/stdc++.h>

#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define INF 0x3f3f3f3f
using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;

const int N=1e3+10;
int n;
double m;
int t;
int dx[8]={1,0,-1,0,1,1,-1,-1},dy[8]={0,1,0,-1,1,-1,1,-1};

int main()
{
    cin>>t;
    while(t--)
    {
        LL ans=0;
        cin>>n>>m;
        LL red=0,green=0,temp;
        temp=100*m-100;
        LL now=n;
        while(now)
        {
            red+=now*100;
            green+=min(10000LL,temp*now);
            now=0;
            now+=red/200;
            ans+=red/10;
            ans+=green/10;
            red=0;
            green=0;
        }
        cout<<ans<<endl;
    }
    return 0;
}

D.丛林木马

题意:

众所周知,如果给你两个数 a,b 要你计算 a×b=c 的值,你就知道要这么做:把每一位相乘并且乘上它们的 10^k 然后相加,其中 k 表示对应数位的幂次。

有一次,可怜的 ZM 不小心把“相乘”中的所有乘法运算都算成了加法,她想让你帮忙算算,这样算出来的结果是多少?

思路:看样例不难得出,结果是a每位的值 x b的长度加上b每位的值 x a的长度其实就是a x b的长度+b x a的长度。

代码

//属于是给我写复杂了QAQ
#include<bits/stdc++.h>

using namespace std;

const int MOD=998244353;

typedef long long LL;

LL quick_power(LL a,LL b,LL p)
{
    LL ans=1;
    while(b)
    {
        if(b&1) ans=(ans%p*a%p)%p;
        b>>=1;
        a=(a%p*a%p)%p;
    }
    return ans%p;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string a,b;
        cin>>a>>b;
        LL ans=0;
        LL la=a.size(),lb=b.size();
        for(LL i=0;i<la;i++)
            ans=(ans%MOD+quick_power(10, la-i-1, MOD)*(a[i]-'0')%MOD*lb%MOD)%MOD;
        for(LL i=0;i<lb;i++)
            ans=(ans%MOD+quick_power(10, lb-i-1, MOD)*(b[i]-'0')%MOD*la%MOD)%MOD;
        cout<<ans%MOD<<endl;
    }
}
#python版本
t=int(input())
for i in range(t):
    a,b=input().split()
    m=min(len(a),len(b))
    print((int(a)*len(b)+int(b)*len(a))%998244353)

E.变异蛮牛

题意:
给定一棵根为 1,且是黑点的有根树。

每个白点相邻所有的点都是黑点,每个黑点相邻所有的点都是白点。换句话说,你可以从根结点开始,按照深度对每个点黑白染色。

现在对于一条两个端点分别是 u,v 的链,定义其长度为:包含的黑点个数 - 包含的白点个数。

请你数一数 长度最大 的链的个数。

思路
本题要求树上有多少个起点和终点均为黑点的路径。
设黑点数为cnt,dfs求黑点的数量,最终答案便为cnt+cnt*(cnt-1)/2;

代码

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N=2e5+10;
vector<int> e[N];
int n,u,v;
LL cnt;

void dfs(int u,int fa,int deep)
{
    if(deep&1) cnt++;
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==fa) continue;
        dfs(v,u,deep+1);
    }
}
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)    e[i].clear();
    cnt=0;
    for(int i=1;i<n;i++){
        cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs(1,0,1);
    cout<<cnt+(cnt-1)*cnt/2<<endl;
}
int main()
{
    int _;
    cin>>_;
    while(_--){
        solve();
    }
    return 0;
}
posted @ 2022-01-23 16:12  车车学不完  阅读(97)  评论(0)    收藏  举报