Codeforces Round #766 (Div. 2)

Posted on 2022-01-20 16:33  Capterlliar  阅读(56)  评论(0编辑  收藏  举报

C. Not Assigning

题意:给出一棵树,要求给边赋权值,使得长度小于等于2的路径权值和均为质数。

解:仔细想想质数都是奇数,奇数+奇数=偶数,那么长度为2的路径权值和要想仍为质数,必须包含2.那么一个结点就不能有两个以上儿子。再画一画发现只能是一条链,那好办了23232323这样子就好了。

D. Not Adding

长见识了。

题意:给出n个数,每个子集的最大公约数(数组中未出现)添加进去,问能添加多少个。( 1 ≤ n ≤ 10)

解:首先排除暴力枚举。考虑分解因数,n√n,也会炸。思考未果,看题解。既然范围在1e6那么一个个枚举它会不会是gcd就可以了。。。能使它是gcd的只有它的倍数,复杂度 nlnn。判断方法:从它的倍数中找出2个能使得它为gcd而不是比它更大的数。介于gcd只会越求越小而且nlnn能过,所以全来一遍就好了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 1000005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n;
int vis[maxx]={0};
int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
signed main() {
//    int T;
//    scanf("%d",&T);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int t;
        scanf("%d",&t);
        vis[t]=1;
    }
    int ans=0;
    for(int i=1;i<maxx;i++){
        if(vis[i])
            continue;
        int t=0;
        for(int j=i;j<maxx;j+=i){
            if(vis[j])
                t=gcd(t,j);
        }
        if(t==i)
            ans++;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

E. Not Escaping

我真傻,真的。

题意:房子着火了(听说学校门口真着火了。。。),一个人要从 (1,1) 爬到 (n,m) 寻找救援。在第 i 层楼移动一个房间需要耗费 x点健康值。楼下到楼上之间有梯子,爬一次梯子增加 hi 点健康值。求最终最大的生命值。

解:看起来很简单的一道dp但WA了很多次。人家说两个窗口之间只有一个梯子,没说一个窗口只搭一个梯子。。。显然只有搭了梯子的房间是有用的,这样总房间个数是1e5而不是1e5*1e5,把起点和终点也加进来获得dp值。然后碰到这种值和左右两边有关的,每层从左到右更新,从右到左更新,最后把梯子的值递上去,over。写法学习了status里一位大佬的,超好看qwq

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 100005
#define eps 0.00000001
#define inf 2e18
//#define int long long
int n,m,k;
ll x[maxx];
struct node{
    int c,d,h;
};
signed main() {
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
        map<int,vector<node>> mp[n+1];
        map<int,ll> dp[n+1];
        for(int i=1;i<=n;i++)
            scanf("%lld",&x[i]);
        for(int i=1;i<=k;i++){
            int a,b,c,d,h;
            scanf("%d%d%d%d%d",&a,&b,&c,&d,&h);
            mp[a][b].push_back(node{c,d,h});
            dp[a][b]=inf;
            dp[c][d]=inf;
        }
        dp[1][1]=0;dp[n][m]=inf;
        for(int i=1;i<=n;i++){
            ll pos=1,now=inf;
            for(auto it=dp[i].begin();it!=dp[i].end();it++){
                auto [j,w]=*it;
                dp[i][j]=now=min(dp[i][j],now+x[i]*(j-pos));
                pos=j;
            }
            pos=m;now=inf;
            for(auto it=dp[i].rbegin();it!=dp[i].rend();it++){
                auto [j,w]=*it;
                dp[i][j]=now=min(dp[i][j],now+x[i]*(pos-j));
                pos=j;
            }
            for(auto it=dp[i].begin();it!=dp[i].end();it++){
                auto [j,w]=*it;
                for(auto [c,d,h]:mp[i][j])
                    dp[c][d]=min(dp[c][d],dp[i][j]-h);
            }
        }
        if(dp[n][m]>=1e18)
            printf("NO ESCAPE\n");
        else
            printf("%lld\n",dp[n][m]);
    }
    return 0;
}
View Code

PS:现在开map组已经可以mp[n+1]了,这样不会超时,否则不管是开里面开外面都会TLE的。

PSS:吐槽一下,发表的时候,