CF337

CF337

集训第一场个人赛,感觉自己后劲不足,虚的很。

虽然最后没看题解出了所有的题,但是我这速度这也太慢了。

A

排个序

B

需要特殊考虑0/1的情况,自己还是不大行,考虑不全面

C

贪心的想,一定是错在后面更划算。然后问题就是前面连续的怎么算。

假设n为k的倍数

F[n] = (F[n-k] + k) * 2;

F[n] = ((F[n-2k]+k)*2 + k) * 2;

层层往下写,就发现规律了

D

一道树形dp,有几个需要特判的细节

#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int head[N] = {0}, to[N*2], nt[N*2], tot = 0, vis[N] = {0};
void add(int x, int y)
{
    ++tot;nt[tot]=head[x];to[tot]=y;head[x]=tot;
    ++tot;nt[tot]=head[y];to[tot]=x;head[y]=tot;
}
int down[N] = {0}, up[N] = {0};
void dfs1(int now, int pre)
{
//    printf("%d --> %d
", pre, now);
    int maxx[2];
    maxx[0] = maxx[1] = 0;
    for(int i = head[now]; i; i = nt[i])
    {
        if(to[i]==pre) continue;
        dfs1(to[i], now);
        if(vis[to[i]]) 
        {
            down[now] = max(down[now], 1);
            if(1>maxx[1])
            {
                maxx[0] = maxx[1];
                maxx[1] = 1;
            }else if(1>maxx[0])
            {
                maxx[0] = 1;
            }
        }
        if(down[to[i]]==0) continue;
        down[now] = max(down[now], down[to[i]] + 1);
        if(down[to[i]]+1>maxx[1])
        {
            maxx[0] = maxx[1];
            maxx[1] = down[to[i]]+1;
        }else if(down[to[i]]+1>maxx[0])
        {
            maxx[0] = down[to[i]]+1;
        }
    }
    
    for(int i = head[now]; i; i = nt[i])
    {
        if(to[i]==pre) continue;
        if(vis[now]) up[to[i]] = max(up[to[i]], 1);
        if(up[now]) up[to[i]] = max(up[to[i]], up[now] + 1);
        if((down[to[i]] && down[to[i]]+1==maxx[1]) || (vis[to[i]] && maxx[1]==1)) 
        {
        //    printf(">>%d %d %d %d<<
", now, to[i], maxx[0], maxx[1]);
            if(maxx[0]) up[to[i]] = max(up[to[i]], maxx[0]+1);
        }
        else if(maxx[1]) 
        {
            up[to[i]] = max(up[to[i]], maxx[1]+1);
        }
    //    printf("debug : %d - %d
", to[i], up[to[i]]);
    }
}
void dfs2(int now, int pre)
{
    for(int i = head[now]; i; i = nt[i])
    {
        if(pre==to[i]) continue;
        if(up[now]) up[to[i]] = max(up[to[i]], up[now]+1);
        dfs2(to[i], now);
    }
}
int main()
{
    int n, m, d, x, y;
    scanf("%d %d %d", &n, &m, &d);
    
    for(int i = 1; i <= m; i++)
    {
        scanf("%d", &x);
        vis[x] = 1;
    }
    
    for(int i = 1; i < n; i++)
    {
        scanf("%d %d", &x, &y);
        add(x, y);
    }
    
    dfs1(1, 0);
    
//    for(int i = 1; i <= n; i++)
//    {
//        printf("%d --  %d vs %d
", i, down[i], up[i]);
//    }
//    
//    printf("

");
    
    dfs2(1, 0);
    
//    for(int i = 1; i <= n; i++)
//    {
//        printf("%d --  %d vs %d
", i, down[i], up[i]);
//    }
    
    int res = 0;
    for(int i = 1; i <= n; i++) if(up[i]<=d && down[i]<=d) res++;
    
    
    
    printf("%d
", res);
}

E

就是先写一个暴力,然后把自己会的优化都用上,然后这题就过了,说实话,恶心。

自己又因为long long的问题白给了好几发

做完题目,转念一想,确实是自己没有思考完全导致的白给。

这(8!*8*1e6 确实大概率会T)

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
ll a[10], rest[10];
int n, res = 1e9, pre[10], tmp, size[10], flag = 0;
vector <int> ve[10];
map <ll, ll> mp;
int count(ll x)
{
    if(mp[x]) return mp[x];
    ll tmp = x;
    ll res = 0;
    for(ll i = 2; i * i <= x; i++)
    {
        if(x%i==0)
        {
            while(x%i==0)
            {
                x /= i;
                res++;
            }
        }
    }
    if(x>1) res++;
    return mp[tmp] = res;
}
bool prime(ll x)
{
    if(x==2 || x==3) return true;
    for(ll i = 2; i * i <= x; i++)
        if(x%i==0) return false;
    return true;
}
int isprime[10] = {0};
void cal(int now)
{
    tmp++;
    if(size[now]==0)
    {
        if(!isprime[now]) tmp += count(a[now]);
        return;
    }
    if(now)
    {
        if(rest[now]) tmp += count(rest[now]);
    }
    for(int i = 0; i < size[now]; i++)
    {
        cal(ve[now][i]);
        if(flag) return;
    }
}
void dfs(int pos)
{
    if(pos==n+1)
    {
        tmp = 0; flag = 0;
        for(int i = 0; i <= n; i++)
        {
            ve[i].clear();
            size[i] = 0;
        }
        for(int i = 1; i <= n; i++)
        {
            size[pre[i]]++;
            ve[pre[i]].push_back(i);
        }
        cal(0);
        if(size[0]==1)
        {
            tmp -= 1;
        }
        if(flag) tmp = 1e9;
        if(tmp < res)
        {
            res = tmp;
        
        }
        return ;
    }
    for(int i = 0; i < pos; i++)
    {
        if(i && rest[i]%a[pos]) continue;
        rest[i] = rest[i] / a[pos];
        pre[pos] = i;
        dfs(pos+1);
        rest[i] *= a[pos];
    }
}
int main()
{

    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    scanf("%lld", a+i);

    sort(a+1, a+n+1, greater<ll>() );
    
    for(int i = 1; i <= n; i++) 
    {
        rest[i] = a[i];
        if(prime(a[i])) isprime[i] = 1;
    }
    
    dfs(1); 

    printf("%d
", res);
}
原文地址:https://www.cnblogs.com/loenvom/p/12173442.html