2022牛客寒假算法基础集训营1 签到题7题

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022牛客寒假算法基础集训营1 签到题7题相关的知识,希望对你有一定的参考价值。

1、L.牛牛学走路

  • 恭喜你 签到成功
#include<bits/stdc++.h>
using namespace std;
int main()
    int T;  cin>>T;
    while(T--)
        int n;  cin>>n;
        string s;  cin>>s;
        int x = 0, y = 0;
        double ans = 0;
        for(char ch : s)
            if(ch=='U')y++;
            if(ch=='D')y--;
            if(ch=='R')x++;
            if(ch=='L')x--;
            double d = sqrt(x*x+y*y);
            ans = max(ans, d);
        
        printf("%.10lf\\n",ans);
    
    return 0;


2、E.炸鸡块君的高中回忆

  • 注意 n=m=1 的特判;
  • 模拟会超时,要推出公式;
  • 公式不唯一,考虑让m个人先进去花掉1次,之后每轮可以进m-1个。
#include<bits/stdc++.h>
using namespace std;
int main()
    int T;  cin>>T;
    while(T--)
        int n, m;  cin>>n>>m;
        if(m==1)
            if(n==1)cout<<"1\\n";
            else cout<<"-1\\n";
        else
            cout<<2*((n-m)/(m-1)+((n-m)%(m-1)!=0))+1<<"\\n";
        
    
    return 0;


3、J.小朋友做游戏

  • 可以发现,每种里面的小朋友都是一样的,没有区别的,所以先将两种小朋友的幸福度分别按从大到小排序 记为 A 和 B 数组;那么最优的方案一定是从 A 和 B 中各选一个前缀;
  • 因此可以求出两个数组的前缀和 然后枚举从 A 中选了多少人, 从B 中选的人数等于总人数减去 A 中的,利用前缀和 𝑂(1)的获得此时的总幸福度;
  • 对于圆圈紧挨着的限制 其实就相当于限制闹腾小朋友最多选 n/2个, 在上面枚举的时候加入该限制即可
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+10;

int a[maxn], b[maxn];
bool cmp(int x, int y)return x>y;

int main()
    int T;  cin>>T;
    while(T--)
        int A, B, n;
        cin>>A>>B>>n;
        for(int i = 0; i < A; i++)cin>>a[i];
        for(int i = 0; i < B; i++)cin>>b[i];
        if(A<(n+1)/2)
            cout<<-1<<"\\n";
            continue;
        
        LL ans = 0;
        sort(a,a+A,cmp);
        sort(b,b+B,cmp);
        for(int i = 0; i < (n+1)/2; i++)ans += a[i];//安静的选一半先
        int p = (n+1)/2, q = 0, cur = (n+1)/2;
        while(cur < n) //选满n个为止
            if(p>=A)ans += b[q++];
            else if(q>=B)ans += a[p++];
            else if(b[q]>a[p])ans += b[q++];
            else ans += a[p++];
            cur++;
        
        cout<<ans<<"\\n";
    
    return 0;


4、H.牛牛看云

  • 提高对数据范围的敏感程度,注意到 𝑛≤1e6而 𝑎𝑖≤1000 可以看到 𝑎[𝑖]范围很小
  • 枚举(n,n)对儿 高达1e12,但是 (𝑖,𝑗)对儿一共也就 10^6种,也就是说极限数据下会有大量重复的值出现
  • 记 cnt[𝑖]表示 𝑖出现的次数。不同情况直接相乘表示(i,j)对出现次数,相同的情况特殊处理。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+10;
LL cnt[1010];
int main()
    int n;  cin>>n;
    for(int i = 1; i <= n; i++)
        int x;  cin>>x;  cnt[x]++;
    
    LL ans = 0, times;
    for(int i = 0; i <= 1000; i++)
        for(int j = i; j <= 1000; j++)
            if(i==j)times = (cnt[i]+cnt[i]*(cnt[i]-1)/2);
            else times = cnt[i]*cnt[j];
            ans += times*(LL)abs(i+j-1000);
        
    
    cout<<ans<<"\\n";
    return 0;


5、F.中位数切分

  • 结论题
  • 证明




#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+10;
int main()
    int T;  cin>>T;
    while(T--)
        int n, m;  cin>>n>>m;
        int cnt = 0;
        for(int i = 1; i <= n; i++)
            int x;  cin>>x;  if(x>=m)cnt++;
        
        int ans = cnt-(n-cnt);
        if(ans <= 0)cout<<"-1\\n";
        else cout<<ans<<"\\n";
    
    return 0;


6、I. B站与各唱各的

推导:

  • 首先注意到句子与句子之间没有办法互相影响 因此答案是一句话的期望乘以 𝑚
  • 由于无法交流 每个人在唱每句时唯一的策略就是随机以 𝑝𝑖的概率决定唱或不唱这一句
  • 又由于 𝑛个人之间没有区别 所以不同人的概率一定是相等的 记为 𝑝
  • 因此 唱失败的概率是 𝑝^𝑛+(1−𝑝)^𝑛 求其最小值得 𝑝=1/2 进而计算可以得到最终答案;

结论:

  • 答案即为𝑚×(2^𝑛−2)/(2^𝑛),除法需要用逆元
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+10;
const int mod = 1e9+7;
LL pows(LL a, LL x, LL p)if(x==0)return 1; LL t = pows(a, x>>1,p);if(x%2==0)return t*t%p;return t*t%p*a%p;
void EXGCD(int a, int b, int &d, int &x,  int & y, int MOD)  if (b==0)  d = a; x = 1; y = 0;  else  EXGCD(b, a % b, d, y, x, MOD); y -= x * (a / b);  
int inv(int a, int MOD)  int d=0, x=0, y=0; EXGCD(a, MOD,  d,  x, y, MOD); return d == 1 ? (x + MOD) % MOD : -1; 

int main()
    int T;  cin>>T;
    while(T--)
        int n, m;  cin>>n>>m;
        LL ans = m*(pows(2,n,mod)-2)%mod*inv(pows(2,n,mod),mod)%mod;
        cout<<ans<<'\\n';
    
    return 0;


7、D.牛牛做数论

  • 结论
    问题一的答案为 2 、 2 × 3 、 2 × 3 × 5 、 2 × 3 × 5 × 7… 这些前若干个素数的积中,最大的且不超过 n 的那一个,如 n=233 ,则答案为2 × 3 × 5 × 7=210 。
    问题二的答案为 [2,n] 中最大的素数。
  • 证明
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int isprime(LL x)
    for(LL i = 2; i*i <= x; i++)
        if(x%i==0)return 0;
    return 1;


int main()
    int T;  cin>>T;
    while(T--)
        int n;   cin>>n;
        if(n==1)cout<<"-1\\n"; continue;
        LL a = 1, b;
        for(LL i = 2; i*a <= n; i++)
            if(isprime(i))a*=i;
        for(b = n; ;b--)
            if(isprime(b))break;
        cout<<a<<" "<<b<<"\\n";
    
    return 0;


以上是关于2022牛客寒假算法基础集训营1 签到题7题的主要内容,如果未能解决你的问题,请参考以下文章

2022牛客寒假算法基础集训营4 签到题7题

2022牛客寒假算法基础集训营1 签到题7题

2022牛客寒假算法基础集训营4 签到题7题

2022牛客寒假算法基础集训营2 签到题7题

2022牛客寒假算法基础集训营6 签到题5题(附基础集训营4-6签到题总结)

2022牛客寒假算法基础集训营6 签到题5题(附基础集训营4-6签到题总结)