牛客小白赛63 A~E

A A A题:

子序列的权值最小值

题目大意:n个数中选出x个数,全部 & \& &一遍,请问最小为多少

做法:根据 & \& &的性质,按位与后只会变小,所以应该贪心,直接选整个数组。

注意特判

代码如下:

/*
coder:sunshine
school:njupt
*/
#include <bits/stdc++.h>
#define endl '\n' //交互题删掉
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    int ans=a[0];
    if(n==1)
    {
        cout<<ans<<endl;
        return 0;
    }else
    {
        for(int i=1;i<n;i++)
        {
            ans=ans&a[i];
        }
    }
    cout<<ans<<endl;
    return 0;
}

B B B题:

魔导师晨拥

题目大意:初始伤害值为2点,有m次攻击机会,每次攻击从左往右所有小兵,最后打英雄,如果恰好击杀一个小兵,则伤害+1,问m次后对英雄造成了多少伤害。

做法:模拟遍历就行

代码如下:

/*
coder:sunshine
school:njupt
*/
#include <bits/stdc++.h>
#define endl '\n' //交互题删掉
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;

const int N = 8;
int a[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    int dmg = 2;
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    while (m--)
    {
        for (auto &c : a)
        {
            if (c - dmg == 0)
            {
                c -= dmg;
                dmg++;
            }
            else
            {
                c -= dmg;
            }
        }
        ans += dmg;
    }
    cout << ans << endl;
    return 0;
}

C C C题:

GCPC总决赛

题目大意:两方有n只队,任意挑选 b a t t l e battle battle,获胜条件是哪只的大爹数量多,求平局,胜局,负局数量。

做法:全排列一下,然后循环判断一下

代码如下:

/*
coder:sunshine
school:njupt
*/
#include <bits/stdc++.h>
#define endl '\n' //交互题删掉
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const int N=5e6+3;
ll n,m,sx,sy,sz,a[N],b[N];
int main()
{
    cin>>n;ll p=1,w=0;
    for(int i=1;i<=n;i++)p=p*i;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)cin>>b[i];
    while(w<p)
    {
        w++;ll x=0,y=0;
        next_permutation(a+1,a+n+1);
        for(int i=1;i<=n;i++)
        {
            if(a[i]>b[i])x++;
            if(a[i]<b[i])y++;
        }
        if(x>y)sx++;
        if(x<y)sy++;
        if(x==y)sz++;
    }
    cout<<sx<<" "<<sy<<" "<<sz;
    return 0;
}

D D D题:

Ginger的大花环

题目大意:有一个环,上面有n位,有k种花费的颜料给环上色,要求是不能出现连续三次相同的颜色环,求花费最小。

做法:是一道贪心思维题。设花费为 w 1 , w 2 , w 3 , … w_1,w_2,w_3,\ldots w1,w2,w3,,求花费最小,即以 w 1 , w 1 , w 2 w_1,w_1,w_2 w1,w1,w2的顺序依次上色,到最后要特判一下,如果刚好 % 3 = = 0 \%3==0 %3==0,不需要改动,如果除不尽的话,就要 将一个 w 1 改为 w 2 ,防止出现 w 1 , w 1 , w 1 的组合 将一个w_1改为w_2,防止出现w_1,w_1,w_1的组合 将一个w1改为w2,防止出现w1,w1,w1的组合

代码如下:

/*
coder:sunshine
school:njupt
*/
#include <bits/stdc++.h>
#define endl '\n' //交互题删掉
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const int N=5;
int w[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=k;i++)
    {
        cin>>w[i];
    }
    sort(w+1,w+k+1);
    if(k==1)
    {
        cout<<"Ginger666"<<endl;
    }else
    {
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            if(i%3) ans+=w[1];
            else ans+=w[2];
        }
        if(n%3)
        {
            ans-=w[1];
            ans+=w[2];
        }
        cout<<ans<<endl;
    }
    return 0;
}

先补了昨天小白月赛63的 E E E

E E E题:

最值区间计数

题目大意:求n个数的全排列中 ( 区 间 m a x = n , 区 间 m i n = 1 ) (区间_{max}=n,区间_{min}=1) (max=n,min=1)的子区间数量,对998244353取模。

即求 ∑ p ∑ i = 1 n ∑ j = i n [ m a x k = i j p k = n ] [ m i n k = i j p k = 1 ] \sum_{p} \sum_{i=1}^{n} \sum_{j=i}^{n}[max_{k=i}^{j} p_k=n][min_{k=i}^{j} p_k=1] pi=1nj=in[maxk=ijpk=n][mink=ijpk=1]

做法:可以用数学方法做:从左往右选 i i i的位置,再从 i i i的右边到最后选 j j j的位置,最左边到 i i i的个数乘以 j j j到最右边的个数即是答案,注意要 × 2 ×2 ×2,也要乘 ( n − 2 ) ! (n-2)! (n2)!,因为 n 和 1 n和1 n1的位置可以互换,并且剩下n-2个数也可以随便排列。


a n s = 2 ( n − 2 ) ! ∑ i = 1 n ∑ j = i + 1 n i ( n − j + 1 ) % 998244533 ans=2(n-2)!\sum_{i=1}^{n} {\sum_{j=i+1}^{n} {i(n-j+1)}}\%998244533 ans=2(n2)!i=1nj=i+1ni(nj+1)%998244533
显然 n = 1 e 6 n=1e6 n=1e6时,上面这个式子时间复杂度为 O ( n 2 ) O(n^2) O(n2),肯定超时了,所以要对式子进行优化,优化到 O ( n l o g n ) O(nlogn) O(nlogn) O ( n ) O(n) O(n)最好。

可以对中间这个式子优化:
∑ i = 1 n ∑ j = i + 1 n i ( n − j + 1 ) = ∑ i = 1 n ( ∑ j = i + 1 n i ⋅ n + ∑ j = i + 1 n − i j + ∑ j = i + 1 n i ) = ∑ i = 1 n [ ( n − i ) ⋅ ( i n + i ) − i ⋅ ∑ j = i + 1 j j ] = ∑ i = 1 n [ i ( n − i ) ( n + 1 ) − i ( i + 1 ) + n 2 ⋅ ( n − i ) ] \sum_{i=1}^{n} {\sum_{j=i+1}^{n} {i(n-j+1)}}\\ =\sum_{i=1}^{n} {(\sum_{j=i+1}^{n} {i\cdot n}+\sum_{j=i+1}^{n} {-ij}+\sum_{j=i+1}^{n} {i})}\\ =\sum_{i=1}^{n} {[(n-i)\cdot (in+i)-i\cdot \sum_{j=i+1}^{j} {j}]}\\ =\sum_{i=1}^{n} {[i(n-i)(n+1)-i\frac{(i+1)+n} {2}\cdot (n-i)]} i=1nj=i+1ni(nj+1)=i=1n(j=i+1nin+j=i+1nij+j=i+1ni)=i=1n[(ni)(in+i)ij=i+1jj]=i=1n[i(ni)(n+1)i2(i+1)+n(ni)]
就可以优化成 O ( n ) O(n) O(n)的时间复杂度

代码如下:

/*
coder:sunshine
school:njupt
*/
#include <bits/stdc++.h>
#define endl '\n' //交互题删掉
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const ll mod = 998244353;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;

    if (n == 1)
    {
        cout << 1 << endl;
    }
    else
    {
        ll ans = 0;
        for (ll i = 1; i <= n; i++)
        {
            ans = (ans + (n - i) * (n * i + i) - (ll)i * (i + 1 + n) * (n - i) / 2ll) % mod;
        }
        for (ll i = 1; i <= n - 2; i++)
        {
            ans = ans * (ll)i % mod;
        }
        ans = ans * 2ll % mod;
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值