【牛客IOI周赛16-普及组】补题,树形DP

A

签到题,本质上是求

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int MOD=1e9+7;
int main()
{
    int n;ll ans=1;cin>>n;
    while(n){
        ans=(ans%MOD*n%MOD)%MOD;
        n--;
    }
    cout<<ans;
}

B 猜数---排序和不排序两种做法

原数组排序,从前以后依次加上,一直加到大于等于给定m 。相当于一种贪心,从最多的差值开始加,一直加到大于m此时遍历的数就为最少改动数。 时间

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

#define ll long long
int num[1000005];
int main(){
    int n,m;
    cin>>n>>m;
    ll sum=0;
    for(int i=0;i<n;++i){
        cin>>num[i];
        sum+=num[i];
    }
    sort(num,num+n);
    int tmp=sum;int ans=1;
    for(int i=0;i<n;++i){
        tmp+=9-num[i];
        if(tmp>=m){
            break;
        }else ans++;
    }
    cout<<ans;
}

IOI赛制要求执行效率,考虑不排序做法:
上面做法排序是为了遵循先加上比较大的差值,那么可以先统计原数组0-9的个数,然后枚举差值即可,常数时间复杂度。

#include <bits/stdc++.h>
using namespace std;
int cnt[10];
int n,m,ans,sum;

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int x;cin>>x;
        cnt[x]++,sum+=x;
    }
    for(int i=0;i<10;i++){
        int d=9-i;//枚举差值,差值无非就是0~9
        int now=cnt[i]*d;
        if(sum+now<m) sum+=now,ans+=cnt[i];
        else{
            ans+=(m-sum)%d==0?(m-sum)/d:(m-sum)/d+1;
            break;
        }
    }
    printf("%d\n",ans);
    return 0;
}

C

找规律,推出递推公式:
看了官方题解觉得这个题出的真不错——f[i]表示i*i的矩阵的方法数

#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;

#define ll long long
const int MOD = 1e9+7;
int nn,n;
ll f[100005];
int main()
{
    cin>>n;
    f[0]=1;f[1]=1;
    for(int i=2;i<=n;++i){
        f[i]=(f[i-1]%MOD+(i-1)%MOD*f[i-2]%MOD)%MOD;
    }
    cout<<f[n]%MOD;
}

D

https://ac.nowcoder.com/acm/contest/5389/D

参考大佬题解https://blog.nowcoder.net/n/9672836159594b519ceebcdb658ab6c2 表示 u 这个节点,最长链小于等于j的最小代价。
转移过程中要用tmp[i]来保存dp[u][i]过程值
转移方程:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e3+7;
const int INF = 0x3f3f3f3f;
int a[N],f[N][N],tmp[N];

vector<int> e[N];
int n,l;
void dfs(int u,int fa){
    f[u][0]=a[u]; //删除自己
    for(auto child : e[u])if(child!=fa){
        dfs(child,u);
        f[u][0]+=*min_element(f[child],f[child]+l); //删除自己 同时子树最长链也小于等于l
        for(int i=1; i<l; ++i)
            tmp[i]=f[u][i],f[u][i]=INF; 
        for(int i=1; i<l;++i){  //不删除自己
            for(int j=0; j<l; ++j){ //子树最长链满足小于等于j
                if(i+j<l) f[u][max(i,j+1)]=min(f[u][max(i,j+1)],tmp[i]+f[child][j]);
                else break;
            }
        }
    }
}

int main(){
    cin>>n>>l;
    for(int i=1;i<=n;++i) cin>>a[i];
    for(int i=1;i<n;++i){
        int u,v;cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs(1,0);
    printf("%d\n",*min_element(f[1],f[1]+l));
    return 0;
}
全部评论

相关推荐

当年还在美团那个倒霉的&nbsp;Peppr&nbsp;团队工作时,我一直有个疑问:这群人每天到底在自嗨什么。每次开会一堆人围着一堆“看起来很高级”的文档转,模板统一、名词复杂、页数感人,每一页都在暗示一件事:“你不懂,是因为你不专业。”但现实是——代码照样写在&nbsp;💩&nbsp;山上,该出问题还是会出问题,这真的很逗,系统一出问题,文档的唯一作用就是证明:“我们当初确实认真写过文档。”所以本质区别到底是什么?是代码质量提升了,还是大家在精神层面完成了一次“工程师&nbsp;cosplay”?有句话说得好潮水退去才知道谁在裸泳。还记得当时的马哥、明哥(图&nbsp;1&nbsp;左)最爱反复强调一句话:“所有场景一定要想到。”、“这个场景为什么没考虑到?”不过他们这些话我是真的听进去了。不然我也不会在一年多前就说:这个项目活不过两年。顺带一提,那段时间还有个固定节目。每次下楼,总能听见我明哥在吐槽不同的人。我从他身后绕过去,经常能听到他一边抽烟一边说:“xx&nbsp;这小子太坑了,回头我一定要跟马哥说说。”于是深谙人情世故但真不会抽烟的我也会从口袋掏出一支低尼古丁含量的烟给自己点上,假意自己什么都没听到什么都不知道,只是来抽烟的。后来我才明白,这可能也是团队文化的一部分:问题永远在别人身上,而我们,永远在复盘里😂。
秋招白月光
点赞 评论 收藏
分享
01-04 14:19
已编辑
重庆科技大学 Java
想和你交朋友的秋田犬...:唉 现在acm已经没那么吃香了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务