9.24省赛题解

9.24省赛题解

A Marjar Cola

题意
给你a、b和可乐瓶和可乐盖,你可以用x个可乐瓶或者y个可乐盖换一瓶可乐(包括1给可乐瓶和可乐盖),问最多能换多少瓶可乐

题解
考虑永远也换不完的情况
1,x == 1 || y == 1(a,b,x,y>=1)
2, x == 2 && y == 2 &&(a >= 2 || b >= 2)

#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int MAX = 1e5 + 10;
const int INF = 1e9 + 7;

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        int x, y, a, b;
        scanf("%d%d%d%d", &x, &y, &a, &b);
        if(x == 1|| y == 1 || (x == 2 && y == 2 && a >= 2)|| (x == 2 && y == 2 && b >= 2)) {
            printf("INF\n");
            continue;
        }
        int ans = 0;
        while(1) {
            if(a < x && b < y) break;
            while(a >= x) {
                int cnt = a / x;
                ans += cnt;
                a %= x;
                a += cnt;
                b += cnt;
            }
            while(b >= y) {
                int cnt = b / y;
                ans += cnt;
                b %= y;
                a += cnt;
                b += cnt;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

C How Many Nines

题意
给你两个日期,问你这两个日期之间有多少个数字’9’

题解1

我的理解:计算两个日期之间的年份出现的9的次数 ,例如2017.7.8-2039.2.23先计算2017-2039(包括2017和2039) 在减去到2017.1.1到2017.7.7出现的9的次数,在加上2039.1.1到2039.2.23

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#define ll long long
using namespace std;
const int MAX = 1e4 + 10;
const int INF = 1e9 + 7;

int a[13];//每月有几个9,一般情况下
int year[MAX];//每年出现9的次数
int run[MAX];//闰年的次数
int sumday[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

inline void init() {
    for(int i = 1; i <= 12; i++) {
        a[i] = 3;
    }
    a[2] = 2;
    a[9] = 33;

    run[1999] = 0;
    int cnt = 0;
    for(int i = 1999; i <= 10000; i++) {
        if(i % 400 == 0 || (i % 100 != 0 && i % 4 == 0)) {
            cnt++;
        }
        run[i] = cnt;
        int cnt9 = 0;
        if(i % 10 == 9) cnt9++;
        if(i / 10 % 10 == 9) cnt9++;
        if(i / 100 % 10 == 9) cnt9++;
        if(i / 1000 % 10 == 9) cnt9++;
        year[i] = cnt9;
    }

    for(int i = 1; i <= 12; i++) {
        sumday[i] += sumday[i - 1];
    }

}

ll solve(int y1, int y2) {//闭区间
    ll ans = 0ll;
    for(int i = y1; i < y2; i++) {
        if(run[i] > run[i - 1]) {
            ans += (366) * year[i] + 66;
        }
        else ans += 365 * year[i] + 65;
    }
    return ans;
}

int main() {
    init();
    int T;
    scanf("%d", &T);
    while(T--) {
        int y1, m1, d1, y2, m2, d2;
        scanf("%d%d%d %d%d%d", &y1, &m1, &d1, &y2, &m2, &d2);
        ll ans = 0ll;
        //开区间
        d1--;

        ans += solve(y1, y2);
        //-前面的
        ans -= (sumday[m1 - 1] + d1) * year[y1];
        if(run[y1] > run[y1 - 1] && m1 >= 3) ans -= year[y1];
        //月
        for(int i = 1; i < m1; i++) ans -= a[i];
        if(run[y1] > run[y1 - 1] && m1 >= 3) ans -= 1;
        //日
        if(m1 == 9) {
            ans -= d1;
        }
            if(d1 >= 29) ans -= 3;
            else if(d1 >= 19) ans -= 2;
            else if(d1 >= 9) ans--;

        //+后面的
        //年
        ans += (sumday[m2 - 1] + d2) * year[y2];
        if(run[y2] > run[y2 - 1] && m2 >= 3) ans += year[y2];

        //月
        for(int i = 1; i < m2; i++) ans += a[i];
        if(run[y2] > run[y2 - 1] && m2 >= 3) ans += 1;

        //日
        if(m2 == 9) {
            ans += d2;
        }
        if(d2 >= 29) ans += 3;
        else if(d2 >= 19) ans += 2;
        else if(d2 >= 9) ans++;

        printf("%lld\n", ans);
    }
    return 0;
}

题解2

具体看代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int MAX = 1e4 + 10;
int sumday[2][13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
                    0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int sum9(int n) {
    int ans = 0;
    while(n) {
        if(n % 10 == 9) ans++;
        n /= 10;
    }
    return ans;
}

bool judge(int x) {
    if((x % 400 == 0) || (x % 4 == 0 && x % 100 != 0)) return 1;
    else return 0;
}

int sum[MAX][13][33];
void init() {
    int presum = 0;
    for(int year = 2000; year <= 9999; year++) {
        for(int mon = 1; mon <= 12; mon++) {

            int maxday = sumday[0][mon];
            if(judge(year)) maxday = sumday[1][mon];

            for(int day = 1; day <= maxday; day++) {
                sum[year][mon][day] = presum + sum9(year) + sum9(mon)+ sum9(day);
                presum = sum[year][mon][day];
            }
        }
    }
}

int main() {
    init();
    int T;
    scanf("%d", &T);
    while(T--) {
        int y1, y2, m1, m2, d1, d2;
        scanf("%d%d%d %d%d%d", &y1, &m1, &d1, &y2, &m2, &d2);
        int ans = sum[y2][m2][d2] - sum[y1][m1][d1] + sum9(y1) + sum9(m1) + sum9(d1);
        printf("%d\n", ans);
    }
}

F Intervals

题意

给出N给区间,问最少删除多少个区间,使得任意三个区间中至少有一个区间不相交

题解

将所有区间 以左端点为键值从小到大排序
然后三个三个一组 进行判断
如果 这三个中有两两相交的 那么就删去右端点最大的 因为这个区间对答案的贡献最小

然后三个区间当中没有两两相交的,那么下一次进来的区间就替换掉右端点最小的。

I Course Selection System

题意

( ∑ i = 1 m H x i ) 2 − ( ∑ i = 1 m H x i ) × ( ∑ i = 1 m C x i ) − ( ∑ i = 1 m C x i ) 2 (\sum_{i=1}^{m} H_{x_i})^2-(\sum_{i=1}^{m} H_{x_i})\times(\sum_{i=1}^{m} C_{x_i})-(\sum_{i=1}^{m} C_{x_i})^2 (i=1mHxi)2(i=1mHxi)×(i=1mCxi)(i=1mCxi)2 这样的式子,求这个式子的最大值。

题解

( ∑ i = 1 m H x i ) 2 = X , ( ∑ i = 1 m C x i ) = Y (\sum_{i=1}^{m} H_{x_i})^2 = X, (\sum_{i=1}^{m} C_{x_i}) = Y (i=1mHxi)2=X(i=1mCxi)=Y然后化简以后得到, ( X − Y ) × X − Y 2 (X - Y) \times X- Y ^ 2 (XY)×XY2所以当 Y Y Y固定, X X X越大越好,所以就dp 一下

dp[i]表示目前y的总和为i的情况下x的最大值。

//先放放,我需要再打一遍
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 50010;
int dp[maxn];
int h[maxn];
int c[maxn];
int main(){
    int T;
    scanf("%d" , &T);
    while(T --){
        int n;
        scanf("%d" , &n);
        int sum = 0;
        for(int i =1 ; i <= n ; ++ i){
                scanf("%d%d" , &h[i] , &c[i]);
                sum += c[i];
        }
        memset(dp , -1 , sizeof(dp));
        for(int i = 1 ; i <= n ; ++ i){
            for(int j = sum ; j >= 0 ; -- j){
                if(dp[j] != -1){
                    dp[j + c[i]] = max(dp[j + c[i]] , dp[j] + h[i]);
                }
            }
            dp[c[i]] = max(dp[c[i]] , h[i]);
        }
        ll ans = 0;
        for(int i = 1 ; i <= sum ; ++ i){
                if(dp[i] != -1)
            ans = max(ans , (long long)dp[i] * (ll)dp[i] - (ll)dp[i] * (ll)i - (ll)i * (ll)i);
        }
        printf("%lld\n" , ans);
    }
    return 0;
}

J Knuth-Morris-Pratt Algorithm

题意

查找给定字符串s中字符串“ cat”和“ dog”的出现总数。

题解

由于字符串长度<1e3 且 T <=30,所以直接模拟就可以了。

题目包括题面里说KMP算法,被迷惑了,所以队友写了kmp板子

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        string s;
        cin >> s;
        int ans = 0;
        for(int i = 0; i <= s.length() - 3; i++) {
            if(s[i] == 'c' && s[i + 1] == 'a' && s[i + 2] == 't') ans++;
            if(s[i] == 'd' && s[i + 1] == 'o' && s[i + 2] == 'g') ans++;
        }
        printf("%d\n", ans);
    }
}
//KMP的算法
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
#define N 1000005
typedef unsigned long long ll;
using namespace std;

char ans[N];
int nxt[N];

void get_next(char *T) {
    nxt[0] = -1;
    int i = 0, j = -1;
    int len = strlen(T);
    while(i < len) {
        if(j == -1 || T[i] == T[j])
            nxt[++i] = ++j;
        else
            j = nxt[j];
    }
}

int KMP(char* S, char* T) {//返回S中T的个数
    get_next(T);
    int res = 0;
    int len1 = strlen(T);
    int len2 = strlen(S);
    int i = 0, j = 0; //i指向模式串T,j指向主串S
    while(j < len2) {
        if(T[i] == S[j]) {
            i++;
            j++;
            if(i == len1) {
                //return j - i + 1;
                res++;
            }
        }
        else {
            i = nxt[i];
            if(i == -1) {
                j++;
                i++;
            }
        }
    }
    return res;
}

char s1[5] = {"cat"}, s2[5] = {"dog"};
char str[N];

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%s", str);
        ll ans = KMP(str, s1);
        ans += KMP(str, s2);
        printf("%lld\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值