18.8.13 考试总结

1.1 问题描述
请构造一颗n 个节点的树,使得其价值最大。
f(d) 表示树上,度数为d 的一个点能够获取的价值。
这棵树的价值为
Σn
i=1 f(di)
di 表示第i 个点的度数
1.2 输入
第一行一个整数T,接下来T 组数据,每组数据输入两行。
第一行输入整数n。第二行输入n ?? 1 个整数f(i) 代表f(1) f(n ?? 1)。
1.3 输出
对于每组数据输出一行,为能够构造的树的最大价值。

一开始我以为是一道树形dp...

考完了才知道原来这个是一道背包问题

n个节点 总共有2n - 2个度数 因为这是一棵树 所以每个节点至少有一个度

关于这道题有一个性质 就是只要每个节点至少有一个度 那么不管剩下的度数如何分配

只要分完了 那么绝对可以连接成一棵树

所以就对剩下的n - 2个度数做背包就好了 初值就是n * 度数为一个的点获得的收益

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5;

int T,n,f[N],dp[N];

int main( ) {

    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d",& T);
    while(T --) {

        scanf("%d",& n);
        for(int i = 1;i < n;i ++) scanf("%d",& f[i]);
        dp[0] = n * f[1];
        for(int i = 1;i <= n - 2;i ++)
          for(int j = 0;j <= i;j ++) {
              dp[i] = max(dp[i],dp[j] + f[i - j + 1] - f[1]);
          }
        printf("%d\n",dp[n - 2]);
        for(int i = 1;i <= n - 2;i ++) dp[i] = 0;
    }
    return 0;
}

2.1 问题描述
给出正整数n 和k,计算j(n; k) =
Σn
i=1 k mod i 的值,其中k mod i 表示k 除以i 的余
数。例如j(5; 3) = 3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5 = 0 + 1 + 0 + 3 + 3 = 7
2.2 输入
输入两个整数n; k。
2.3 输出
输出一个整数结果。

这个我考试的时候就做出来了结果空间开爆了 无语

就是一个对于模数分块的问题 把商一样的魔术分成一块 就降低复杂度到需要的就可以了

代码

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;

const int N = 1e7 + 5;

ll n,k,shang[N],ans = 0,lf,rg;
int dep = 0;

struct beishu {
    ll l,r,tim;
}kuai[200];

int main( ) {

    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    scanf("%I64d%I64d",& n,& k);
    ll s = k;
    while(s) {
        dep ++;
        s /= 10;
    }
    if(dep <= 7) {
        for(int i = 1;i <= min(n,k);i ++) {
            shang[i] = k / i;
        }
        for(int i = 1;i <= min(n,k);i ++) {
            ans += k - shang[i] * i;
        }
        if(n > k) {
            ans += (n - k) * k;
        }
    }
    else {
        bool tag = false;
        ll cut = 2; int num = 0;
        for(int i = 100;i >= 1;i --) {

            lf = k / (i + 1) + 1;
            rg = k / i;
            if(rg > n || lf > n) {
                tag = true; cut = i;
                break;
            }
            kuai[++ num].l = lf;
            kuai[num].r = rg;
            kuai[num].tim = i;
        }
        for(int i = 1;i <= min(k / 101,n);i ++) {
            shang[i] = k / i;
        }
        for(int i = 1;i <= min(k / 101,n);i ++) {
            ans += k - shang[i] * i;
        }
        if(num > 0) {
            for(int i = 1;i <= num;i ++) {
                ll timm = kuai[i].r - kuai[i].l + 1;
                ans += k * timm - kuai[i].tim * (kuai[i].l + kuai[i].r) * timm / 2;
            }
            if(tag) {
                ll lf = kuai[num].r + 1;
                ll tim = kuai[num].tim - 1;
                ll timm = n - lf + 1;
                ans += k * timm - tim * (lf + n) * timm / 2;
            }
        }
        if(n > k) {
            ans += (n - k) * k;
        }
    }
    printf("%I64d",ans);
    return 0;
}

3.1 问题描述
n 个霍比特人打算在佛罗多的家里过夜。佛罗多有n 张床位和m 个枕头(n m)。n 张床
位排成一列。每个霍比特人需要一张床和至少一个枕头睡觉,但是,每个人都想要尽可能多的
枕头。当然,并不总是可以平等地分享枕头,但如果霍比特人比他邻居少至少两个枕头,那么
他会受伤。
佛罗多将睡在排在第k 个的床上。他可以拥有多少枕头,以便每个霍比特人至少有一个枕
头,每个枕头都被给予霍比特人,而且没有人受伤?
3.2 输入
第一行一个整数T,接下来T 组数据。
每组数据输入一行,三个整数n; m; k。
3.3 输出
对于每组数据一行,输出佛罗多最多拥有多少枕头。

这道题真的非常简单了 但是考试的时候 我只考虑了放一边枕头没办法放完

忘记了他两边都有可能放不下

就是一个sd二分

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;

int T;
ll n,m,k,s[100005],ans;

bool check(ll num) {

    ll t1,t2;
    if(num > k) {
        t1 = (num - k + 1 + num) * k / 2;
    }
    else {
        t1 = (num + 1) * num / 2;
        t1 += k - num;
    }
    if(num > n - k + 1) {
        t2 = (num - n + k + num) * (n - k + 1) /2;
    }
    else {
        t2 = (num + 1) * num / 2;
        t2 += n - k + 1 - num;
    }
    if(t1 + t2 - num <= m) return true;
    return false;
}

ll solve(ll l,ll r) {

    ll ans = 0;
    while(l <= r) {
        ll mid = (l + r) >> 1;
        if(check(mid)) {
            ans = mid;
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }
    }
    return ans;
}

int main( ) {

    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    scanf("%d",& T);
    while(T --) {

        scanf("%I64d%I64d%I64d",& n,& m,& k);
        ans = solve(1,m);
        printf("%I64d\n",ans);
    }
    return 0;
}

总之还是不够细心 蒟蒻

原文地址:https://www.cnblogs.com/Rubenisveryhandsome/p/9470352.html

时间: 2024-11-06 12:21:18

18.8.13 考试总结的相关文章

2016.6.13 考试总结

一.哲哲回家 [题目描述]: 哲哲放学了,准备坐公交车回家.因为急着回家看MSN战士,所以他想用最短的时间回家,但是因为学校离家里比较远,有时候他需要转几趟车才可以回家.等车是需要一段时间的,而且每辆公交车的速度不一样,哲哲晕掉了,不知道怎样才可以在最短的时间里回家,作为一名cjoier,你应该帮帮他. 现在一直哲哲所在的城市有N个公交站点(学校在一号站点,哲哲家在N号站点)和M条公交线路,每条公交线路是一个有序集合,公交线路i包含Pi个站点a[i,1],a[i,2]…a[i,Pi],表示i号公

5.13考试整理 x

5.13五一清北基础班试题 1.洛谷P1149 火柴棒等式(时空限制1s / 128MB) 题目描述 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注意: 1.加号与等号各自需要两根火柴棍 2.如果A≠B,则A+B=C与B+A=C视为不同的等式(A.B.C>=0) 3.n根火柴棍必须全部用上 输入输出格式 输入格式: 输入文件matches.in共一行,又一个整数n(n<=

2017/8/13 考试吐槽

2017 8 13 得分:160 联考最后一天--因为不会对拍日常爆炸-- A.最长上升子串 题意:给出一个序列,允许修改一次元素,求出这个序列最长子串. 这个玩意我刚开始以为是个线性$DP$,然后--细节巨多,写出来之后出一个数据卡一个-- 慌得我直喝水直上厕所--然后转到第$8$趟的时候,由于厕所比我在的那个窝风角落凉快,我的脑子算是冷静了下来,仔细一想,卧槽这不是$DP$!我可以先正序求出以每个元素开头子串长度,再倒序求出每个元素结尾子串长度,之后枚举修改位置,检查修改效果!$mdzz$-

5.13考试

5.13五一清北基础班试题 1.洛谷P1149 火柴棒等式(时空限制1s / 128MB) 题目描述 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注意: 1.加号与等号各自需要两根火柴棍 2.如果A≠B,则A+B=C与B+A=C视为不同的等式(A.B.C>=0) 3.n根火柴棍必须全部用上 输入输出格式 输入格式: 输入文件matches.in共一行,又一个整数n(n<=

Day 18(06/13) 文件处理、函数

一.文件处理流程 二.基本操作 2.1 文件操作基本流程初探 2.2 文件编码 2.3 文件打开模式 2.4 文件内置函数flush 2.5 文件内光标移动 2.6 open函数详解 2.7 上下文管理 2.8 文件的修改 一.文件处理流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 二.基本操作 2.1 文件操作基本流程初探 f = open('chenli.txt') #打开文件 first_line = f.readline() print('first li

18.2.13 codevs1012 最大公约数和最小公倍数问题

1012 最大公约数和最小公倍数问题 2001年NOIP全国联赛普及组 题目描述 Description 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数 条件:  1.P,Q是正整数 2.要求P,Q以x0为最大公约数,以y0为最小公倍数. 试求:满足条件的所有可能的两个正整数的个数. 输入描述 Input Description 二个正整数x0,y0 输出描述 Output Description 满足条件的所有可

18.2.13 codevs1212 最大公约数

题目描述 Description 求两个数A和B的最大公约数. 1<=A,B<=2^31-1 输入描述 Input Description 两个整数A和B 输出描述 Output Description 最大公约数gcd(A,B) 样例输入 Sample Input 8 12 样例输出 Sample Output 4 1 #include <iostream> 2 #include<math.h> 3 4 using namespace std; 5 6 long di

18.11.13 二叉树三则

二叉树的深度(10分) 题目内容: 给定一棵二叉树,求该二叉树的深度 二叉树深度定义:从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的节点个数为树的深度 输入格式: 第一行是一个整数n,表示二叉树的结点个数.二叉树结点编号从1到n,根结点为1,n <= 10 接下来有n行,依次对应二叉树的n个节点. 每行有两个整数,分别表示该节点的左儿子和右儿子的节点编号.如果第一个(第二个)数为-1则表示没有左(右)儿子 输出格式: 输出一个整型数,表示树的深度 输入样例: 3 2

总结2017.3.13考试

1.本题考查List接口与实现类的关系.Java的List接口有3个实现类,分别是ArrayList.LinkedList.Vector,它们用于存放多个元素,维护元素的次序,而且允许元素重复.本题应选择D. 4.本题考查HashMap集合类的特性.Java的HashMap 类是一个散列表,它存储的内容是键值对(key-value)映射.HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io.Serializable接口.因为它属于Map接口的类,所以实现