牛客寒假算法基础集训营1

牛客寒假算法基础集训营1


题目链接:https://ac.nowcoder.com/acm/contest/3002?&headNav=www

A honoka和格点三角形

题意:给出一个n*m的矩阵,找出有如下条件的三角形的个数:

1.三角形的三个顶点均为格点,即横坐标和纵坐标均为整数。
2.三角形的面积为1
3.三角形至少有一条边和x轴或y轴平行。

思路:满足条件的三角形有两类:1、底为1,高为2;2、底为2,高为1。

使底边分别平行于x轴和y轴,其中会有重复的,计算中减去即可。

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<string.h>
using namespace std;
const int mod = 1e9 + 7;

int main()
{
    long long n, m;
    cin >> n >> m;
    long long ans1, ans2, ans3, ans4;
    ans1 = (2 * (n - 1) % mod * m % mod * (m - 2)) % mod;
    ans2 = (2 * (m - 1) % mod * m % mod * (n - 2)) % mod;
    ans3 = (2 * (m - 1) % mod * (n - 2) % mod * (n - 2)) % mod;
    ans4 = (2 * (n - 1) % mod * (m - 2) % mod * (n - 2)) % mod;
    cout << (ans1 + ans2 + ans3 + ans4) % mod << endl;
    return 0;
}

B kotori和bangdream

签到题,根据概率算期望

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<string.h>
using namespace std;

int main()
{
    double n,x,a,b;
    scanf("%lf%lf%lf%lf",&n,&x,&a,&b);
    double ans=n*(x/100)*a+n*(1-x/100)*b;
    printf("%.2f\n",ans);
    return 0;
}

D hanayo和米饭

签到题,标记数组,遍历找到未被标记的位置

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<string.h>
using namespace std;

int main()
{
    int n,ans;
    int arr[100005];
    scanf("%d",&n);
    memset(arr,0,sizeof(arr));
    for(int i=0;i<n-1;i++){
        int a;
        scanf("%d",&a);
        arr[a]=1;
    }
    for(int i=1;i<n+1;i++){
        if(arr[i]==0){
            ans=i;
            break;
        }
    }
    printf("%d\n",ans);
    return 0;
}

E rin和快速迭代

题意:给出一个正整数X,求其因子数,令X等于其因子数,再求X因子数并X等于其因子数,不断迭代下去,最终X会等于2。求这个过程需要迭代多少次

思路:O( n \sqrt{n} n ) 求因子数 模拟过程

for循环中i开long long

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<string.h>
using namespace std;

const int mod = 1e9 + 7;

int main()
{
    long long n;
    cin >> n;
    int ans = 0;
    while(n != 2){
        ans++;
        int num = 0;
        for(long long i = 1; i * i <= n; i++){
            if(n % i == 0){
                if(i * i == n) num++;
                else num += 2;
            }
        }
        n = num;
    }
    cout << ans << endl;
    return 0;
}

G eli和字符串

题意:截取一段最短的连续字串,子串中至少包括K个相同的某个字母

思路:尺取法,,用map保存了尺取维护的区间中的字母的个数

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<string.h>
#include<map>
using namespace std;

const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int main()
{
    int n, k;
    string s;
    cin >> n >> k;
    cin >> s;
    map <char, int> mp;
    int L = 0, R = 0, ans = INF, sum = 0;
    while(1){
        while(R < n && sum < k){
            mp[s[R]] += 1;
            sum = max(sum, mp[s[R]]);
            R += 1;
        }
        if(sum < k) break;
        ans = min(R - L, ans);
        mp[s[L]] -= 1;
        if(s[L] == s[R - 1]) sum -= 1;
        L += 1;
    }

    if(ans == INF) cout << -1 << endl;
    else cout << ans <<endl;

    return 0;
}

H nozomi和字符串

题意:一个 “01”串而言,每次操作可以把 0 字符改为 1 字符,或者把 1 字符改为 0 字符,最多可操作K次。在操作之后找出一个尽可能长的连续子串,这个子串上的所有字符都相同。

思路:K次操作,只能是全部将0变成1,或者全部将1变成0。全部将0变成1:先移动右端点,遇到0则将可操作次数-1(将0变为1,但不改变真值),如果可操作次数为0,就移动左端点,当左端点遇到0,可操作次数+1,重新循环。全部将1变成0,操作相同。两种可能都执行找出最大值。

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<string.h>
#include<map>
using namespace std;

const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int main()
{
    int n, k;
    string s;
    cin >> n >> k;
    cin >> s;
    int L = 0, R = 0, num = 0, ans = 0;
    //将0变为1
    while(1){
        while(R < n){
            if(s[R] == '0' && num == k) break;
            if(s[R] == '0' && num < k){
                num++;
            }
            R++;
        }
        ans = max(R - L, ans);
        if(R >= n) break;
        while(s[L] != '0') L++;
        num--;
        L++;
    }
	//将1变为0
    L = 0, R = 0, num = 0;
    while(1){
        while(R < n){
            if(s[R] == '1' && num == k) break;
            if(s[R] == '1' && num < k){
                num++;
            }
            R++;
        }
        ans = max(R - L, ans);
        if(R >= n) break;
        while(s[L] != '1') L++;
        num--;
        L++;
    }
    cout << ans << endl;
    return 0;
}

I nico和niconiconi

题意:给出一个长度为n字符串,“nico” 计a分,“niconi” 计b分,“niconiconi” 计c分。已被计数过的字符不能重复计数,找出最大的计数分数。

思路:线性DP

if (s.substr(i - 3, 4) == “nico”) dp[i]=max(dp[i],dp[i−4]+a)

if (s.substr(i - 5, 6) == “niconi”) dp[i]=max(dp[i],dp[i−6]+a)

if (s.substr(i - 9, 10) == “niconiconi”) dp[i]=max(dp[i],dp[i−10]+a)

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<string.h>
#include<map>
using namespace std;

typedef long long ll;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int e = 3e5 + 5;

ll dp[e];

int main()
{
    ll n, a, b, c;
    string s;
    cin >> n >> a >> b >> c;
    cin >> s;

    dp[0] = 0;
    for(int i = 1; i < n; i++){
        dp[i] = dp[i - 1];
        if(i >= 3 && s.substr(i - 3, 4) == "nico"){
            dp[i] = max(dp[i], dp[i - 4] + a);
        }
        if(i >= 5 && s.substr(i - 5, 6) == "niconi"){
            dp[i] = max(dp[i], dp[i - 6] + b);
        }
        if(i >= 9 && s.substr(i - 9, 10) == "niconiconi"){
            dp[i] = max(dp[i], dp[i - 10] + c);
        }
    }
    cout << dp[n - 1] << endl;
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值