牛客网NOIP赛前集训营-普及组(第四场)Solution

无聊去水了场普及组结果ak了(逃
A-新个税
按照题目要求直接模拟即可
需要注意的是小于等于5000元的情况,否则只有90分

#include <cstdio>
#include <stdlib.h>
using namespace std;
int al, sa, de;
void stop() {
    printf("%d\n", al - de);
    exit(0);
}
 
int main() {
    scanf("%d", &al);
    if (al <= 5000) {
        printf("%d", al);
        return 0;
    }
    int sa = al / 100 - 50;
    if (sa <= 30) de += sa * 3, stop();
    else de += 90, sa -= 30;
    if (sa <= 90) de += sa * 10, stop();
    else de += 900, sa -= 90;
    if (sa <= 130) de += sa * 20, stop();
    else de += 2600, sa -= 130;
    if (sa <= 100) de += sa * 25, stop();
    else de += 2500, sa -= 100;
    if (sa <= 200) de += sa * 30, stop();
    else de += 6000, sa -= 200;
    if (sa <= 250) de += sa * 35, stop();
    else de += 8750, sa -= 250;
    de += sa * 45;
    stop();
}

B-二分之一
高精度乘法
小数点后共n位,前几位为零,后几位为 5 n 5^n 5n

#include <cstdio>
#define N 1005
 
using namespace std;
int num[N];
 
int main() {
    int al = 1, n, x;
    scanf("%d", &n);
    num[1] = 1;
    for (int i = 1; i <= n; ++i) {
        x = 0;
        for (int j = 1; j <= al; ++j) {
            num[j] = num[j] * 5 + x;
            x = num[j] / 10;
            num[j] %= 10;
        }
        if (x > 0) num[++al] = x;
    }
    printf("0.");
    for (int i = al; i < n; ++i) {
        putchar('0');
    }
    for (int i = al; i >= 1; i--) {
        printf("%d", num[i]);
    }
    putchar('\n');
    return 0;
}

C-部分和
给的代码已经暗示的很清楚了
k k k维的前缀和时间复杂度为 θ ( k × n k ) \theta(k\times n^k) θ(k×nk)
对于题目中的每位只有 0 , 1 0,1 0,1两种情况所以时间复杂度为 θ ( k × 2 k ) \theta(k\times2^k) θ(k×2k)
θ ( n l o g n ) \theta(nlogn) θ(nlogn)

#include <cstdio>
#define N 1 << 21
using namespace std;
long long a[N];
int main() {
    int n, k = 0;
    scanf("%d", &n);
    for (int nn = n; nn > 1; nn /= 2) k++;
    for (int i = 0; i < n; ++i)
        scanf("%d", &a[i]);
    for (int i = 0; i < k; ++i) {
        int now = 1 << i;
        for (int sta = 0; sta < n; ++sta)
            if (sta & now) a[sta] += a[sta ^ now];
    }
    for (int sta = 0; sta < n; ++sta)
        printf("%d\n", a[sta]);
    return 0;
}

D-重蹈覆辙
其实题目又疯狂暗示你了…
"重蹈覆辙"说明后来有循环的嘛
本题分三步

  1. 状压DP找出规律,发现 f ( i ) = 2 × f ( i − 1 ) + f ( i − 3 ) f(i)=2\times f(i-1)+f(i-3) f(i)=2×f(i1)+f(i3)
  2. 还要取模10007…
    继续暴力找f(i - 2) == f(j - 2) && f(i - 1) == f(j - 1) && f(i) == f(j)
  3. 找到 i = 4 , j = 10010 i=4,j=10010 i=4,j=10010,写代码
#include <cstdio>
#include <iostream>
#include <string>
#define MOD 10007
 
using namespace std;
int f[MOD];
string st;
int main() {
    cin >> st;
    int len = st.size(), x = 0;
    for (int i = 0; i < len; ++i) {
        x = (x * 10 + st[i] - '0') % (MOD - 1);
    }
    f[1] = 1;
    f[2] = 2;
    f[3] = 5;
    for (int i = 4; i <= x; ++i) {
        f[i] = (f[i - 1] * 2 + f[i - 3]) % MOD;
    }
    printf("%d\n", f[x]);
    return 0;
}

总结:码量奇短

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值