首页 > 其他分享 >暑假集训二[LCIS,平凡的函数,那一天她离我而去,矩形]

暑假集训二[LCIS,平凡的函数,那一天她离我而去,矩形]

时间:2022-10-09 10:11:48浏览次数:46  
标签:fr LCIS int wmx 暑假 dis 集训 dp define

暑假集训2

LCIS

首先我赛时打了个\(n ^ {4}\)的暴力,因为一个转移的地方忘记加max了,然后拿了\(70\),本来以为改改也就T了结果它加了个\(max\)就\(A\)了.....这数据也是没谁了

暴力
#include <bits/stdc++.h>
#define int long long
#define LL long long
#define Re register int
#define LD double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(Re x = y; x <= z; x ++)
#define fp(x, y, z)for(Re x = y; x >= z; x ++)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')

#define pr pair<int , int >
#define mk(x, y) makr_pair(x, y)
using namespace std;
namespace kiritokazuto{
    auto read = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}
/*
咖啡不断加加加
加到厌倦
*/

using namespace kiritokazuto;
const int maxn = 3e4 + 100, Inf = 2147483647;

/*
虽然一看就知道是DP
可是咋又要推柿子
一个普遍适用的定义柿
dp[i][j]第一个串在第i位,第二个串在第j位
表示1 ~ i和1 ~ j中以i和j结尾最长公共上升子序列
然鹅很明显有一个n ^ 2暴力
啊呸, n ^ 4?????
我靠,我tm看成子序列了...
*/
int wmxa[maxn], wmxb[maxn];
int n;
int dp[4010][4010];
int ans = -0x7fffffffffffffff;
fuc(LL, maxx)(LL x, LL y){ return (x > y) ? x : y; }
//咱只求n ^ 4能多拿点分!
signed main(){
    frein(lc);
    freout(lc);
    n = read();
    fr(i, 1, n)wmxa[i] = read();
    fr(i, 1, n) wmxb[i] = read();
    fr(i, 1, n){
        fr(j, 1, n){
            if (wmxa[i] == wmxb[j]){
                dp[i][j] = 1;
                // 这个不加,因为我求的是区间
                    //rnm区间好难写,还是写终止吧
                fr(l, 1, i){
                    fr(r, 1, j){
                        if (wmxa[l] == wmxb[r] && wmxa[i] > wmxa[l]){
                            // dp[i][j] = 1;
                            dp[i][j] = maxx(dp[i][j], dp[l][r] + 1ll);
                            // printf("dp[%d][%d] == %d  dp[%d][%d] == %d\n", l, r, dp[l][r], i, j, dp[i][j]);
                        }
                        else if (wmxa[l] == wmxb[r] && wmxa[i] == wmxa[l] && wmxb[j] == wmxb[r]){
                            dp[i][j] = maxx(dp[i][j], dp[l][r]);
                        }
                        else{
                            dp[i][j] = maxx(1, dp[i][j]);
                        }
                        ans = maxx(ans, dp[i][j]);
                    }
                }
            }
        }
    }

    // ki;
    // fr(i, 1, n){
    //     fr(j, 1, n){
    //         printf("dp[%d][%d] == %d\n", i, j, dp[i][j]);
    //     }

    // }
    write(ans);
    return 0;
}
/*
7
2 3 7 7 8 9 5
7 8 9 1 1 1 1
*/

然后是\(n ^ {2}\)并且压维的正解(wy还说他研究出\(O(n)\)的....(想多了), 虽然这个\(n ^ {2}\)是他的)

  • \(dp[i][j]\)表示序列\(a\)前\(i\)个数(不一定以i为结尾)序列\(b\)中以\(j\)为结尾的最长LCIS(限制一个结尾是为了保证上升,限制\(a\)也行)
    • 首先来\(n ^ {3}\)的,如果\(a[i] != b[j]\)直接跳,否则就去找一个 \(k\in[1, j - 1]\)中\(dp[i - 1][k]\)最大的,同时\(b[k] < b[j]\)的来加一转移
    • 优化成\(n ^ {2}\)的就是在第二层里一直维护一个\(Max\)就行
    • 最后因为只和\(i\), \(i - 1\)有关系,可以压掉一维
wy
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int mx=3100+100;
const int Inf=0x7fffffff;
ll f[mx],a[mx],b[mx],n;
void MYH(){
    scanf("%lld",&n);
    for(int i=1;i<=n;++i){
        scanf("%lld",&a[i]);
    }
    for(int i=1;i<=n;++i){
        scanf("%lld",&b[i]);
    }
    for(int i=1;i<=n;++i){
        ll Max=0;
        for(int j=1;j<=n;++j){
            f[j]=f[j];
            if(a[i]>b[j])Max=max(Max,f[j]);
            if(a[i]==b[j])f[j]=Max+1;
        }
    }
    ll ans=0;
    for(int i=1;i<=n;++i){
        ans=max(ans,f[i]);
    }
    printf("%lld\n",ans);
}
int main(){
    freopen("lc.in","r",stdin);
    freopen("lc.out","w",stdout);
    MYH();
    return 0;
}

平凡的函数

其实就是个改一改的欧拉筛,(我赛时都能切的大水题)

  • 因为\(f(p ^ {c}) = p \oplus c\) (\(p\)为质数)所以相当于所有质数的\(f\)都已知了,又因为要通过质数筛出所有数,自然就想到了线性筛,因为有指数,又想到了唯一分解定理...然后就自然写出来了
here
#include <bits/stdc++.h>
#define LL long long
#define Re register int
#define LD double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(Re x = y; x <= z; x ++)
#define fp(x, y, z)for(Re x = y; x >= z; x ++)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')
#define WMX aiaiaiai~~
#define pr pair<int , int >
#define mk(x, y) makr_pair(x, y)
using namespace std;
namespace kiritokazuto{
    auto read = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}
/*
普通的disco我们普通地摇
旁边普通的路人在普通地尖叫
*/
/*
dp[1] = 1;
dp[p ^ c] = p ^ c
那么p或者c等于1的时候不就有了
这玩意怎么感觉像推啊????
啊呸
没看到素数...
那么他俩互质
他俩因子也互质呗
...那我筛出素数来直接乘不就完了??
《唯一分解定理》
*/

using namespace kiritokazuto;
const int maxn = 5e7 + 10;//能开下??
//刚才想到了之前最小质因数那个题,感觉可以用,但是感觉晒不出来啊..
//试试吧
//tnnd没有l
int isprime[maxn];
LL prime[maxn], cnt = 0;
LL wmx[maxn];
//虽然但是,这玩意能过样例????
//但是为啥它会停一下啊
//T飞吧???

//话说他为啥一个标准IO一个文件IO??
LL ans = 0;
fuc(LL, qpow)(LL x, LL y){//为啥这个题连个模数都不给..
    LL res = 1;
    while (y){
        if (y & 1)res = (res * x);
        x = (x * x);
        y >>= 1;
    }
    return res;
}
fuc(void, getprime)(int x){
    memset(isprime, 1, sizeof(isprime));
    isprime[1] = 0;
    fr(i, 2, x){
        if (isprime[i]){
            prime[++cnt] = i;
            wmx[i] = i ^ 1;//素数直接搞
        }
        for (Re j = 1; j <= cnt && i * prime[j] <= x; j++){
            isprime[i * prime[j]] = 0;
            wmx[i * prime[j]] = wmx[prime[j]] * wmx[i];//i和prime[j]互质
            if (i % prime[j] == 0){
                LL tmp = i * prime[j];
                int cot = 0;
                LL tot = 1;
                while (tmp % prime[j] == 0){
                    tmp /= prime[j];
                    cot++;
                    // tot = tot * prime[j];
                }

                tot = qpow(prime[j], cot);
                wmx[tot] = prime[j] ^ cot;
                if (tmp != 1){
                    wmx[i * prime[j]] = wmx[tot] * wmx[tmp];
                }
                break;
            }

        }
        ans += wmx[i];
    }
}

int n;
//话说我打表????????

/*
ri
控制不住想打表的冲动了
50000跑
3904.00000000ms
已经不行了

*/
/*
e..好像我判断条件和筛的时候一样
em...改了改
好像快了
拍了一会
好像没问题
*/
signed main(){
    frein(func);
    freout(func);
    wmx[1] = 1;
    // LD st = clock();
    n = read();
    getprime(n);
    // fr(i, 1, cnt){
    //     write(prime[i]);
    //     fk;
    // }
    // fr(i, 1, n){
    //     if (isprime[i])continue;
    //     fr(j, 1, cnt){
    //         if (i % prime[j] == 0){
    //             int cot = 0;
    //             LL tmp = 0;
    //             int ii = i;
    //             while (ii % prime[j] == 0){
    //                 ii /= prime[j];
    //                 cot++;
    //                 // tmp = tmp * prime[j];
    //             }
    //             tmp = qpow(prime[j], cot);
    //             wmx[tmp] = prime[j] ^ cot;
    //             if (ii){
    //                 wmx[i] = wmx[ii] * wmx[tmp];
    //                 //ii此时已经有值了
    //             }
    //             else{
    //                 break;
    //             }
    //         }
    //     }
    // }
    // fr(i, 1, n){
    //     ans += wmx[i];
    // }
    write(ans + 1);
    // ki;
     // LD ed = clock();
     // printf("%.8lf ", ed - st);
    return 0;
}

那一天她离我而去

正解是分层最短路,因为出\(1\)和回\(1\)的点的二进制位至少有一位不同,所以他俩至少被分在不同组一次...然后就瞎搞呗

std
#include <bits/stdc++.h>
#define LL long long
#define Re register int
#define LD double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(Re x = y; x <= z; x ++)
#define fp(x, y, z)for(Re x = y; x >= z; x ++)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')
#define WMX aiaiaiai~~
#define pr pair<int , int >
#define mk(x, y) makr_pair(x, y)
using namespace std;
namespace kiritokazuto{
    auto read = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}
/*
梦里海市云霞
梦外羽化成她
水中月镜中花
*/
/*
悄悄看了一眼T4
md
不可做
看到期望就发怵
*/
using namespace kiritokazuto;
int t;
int n, m;
const int maxn = 2e5 + 100, Inf = 20000000;//这玩意爆int
struct Node{
    int to, next, dis;
}wmx[maxn << 1];
//这不是昨天的二维dij吗?
//不建反图直接判?
//呃呃呃其实感觉王一昨天的枚举更diao来着
//内存好小啊
//还是枚举吧
//二维开不下
int head[maxn], len = 0;
int Head[maxn];
fuc(void, Qian)(int from, int to, int dis){
    wmx[++len].to = to;
    wmx[len].next = head[from];
    wmx[len].dis = dis;
    head[from] = len;
}
int dis[maxn];
int ans;
deque <int> q;
random_device seed;
mt19937 rrand(seed());
//我把和1相连的全砍一遍
//强行更改最短路

/*
日
调了半天
记住是记住了成对变换从零开始
就是习惯打1.............
*/
int vis[maxn];
fuc(void, Spfa) (int x){
    mes(vis, 0);
    mes(dis, 0x3f);

    q.push_front(x);
    vis[1] = 1;
    dis[x] = 0;
    while (!q.empty()){
        int top = q.front();
        q.pop_front();
        vis[top] = 0;
        for (Re i = head[top]; i; i = wmx[i].next){
            int to = wmx[i].to;
            int diss = wmx[i].dis;
            // if (diss == -Inf){
            //     //  pRef("KKKKKKKKKK to = %d\n", to);

            //     continue;
            // }
            if (dis[to] > dis[top] + diss){
                dis[to] = dis[top] + diss;
                if (vis[to])continue;
                // q.push_back(to);
                if (rrand() & 1)q.push_back(to);
                else q.push_front(to);
                vis[to] = 1;
                // vis[to] = 1;
            }
        }
    }
    return;
}


fuc(void, init)(){
    ans = INT_MAX;
    len = 0;
    // fr(i, 1, n)vis[i] = 0;
    // mes(dis, 33);
    //5558192971
    mes(head, 0);
}
signed main(){
     frein(leave);
     freout(leave);
    t = read();
    while (t--){
        init();
        n = read();
        m = read();
        fr(i, 1, m){
            int x = read(), y = read(), z = read();
            Qian(x, y, z);Qian(y, x, z);
        }
        for (Re i = head[1];i;i = wmx[i].next) Head[wmx[i].to] = head[wmx[i].to];
        Re now = len;
        for (Re i = 0;n >> i;++i){
            len = now;
            for (Re j = head[1];j;j = wmx[j].next){
                Re to = wmx[j].to;
                if (to & (1 << i)) Qian(n + 1, to, wmx[j].dis);
                else Qian(to, n + 2, wmx[j].dis);
            }
            Spfa(n + 1);
            ans = min(ans, dis[n + 2]);
            for (Re j = head[1];j;j = wmx[j].next) head[wmx[j].to] = Head[wmx[j].to];
            head[n + 1] = head[n + 2] = 0;
        }
        write((ans == 0x3f3f3f3f) ? -1 : ans);
        ki;

    }
    return 0;
}

我糊了一个暴力的做法,就是把和一相邻的点都断一次,然后从它跑到一,最后再加上它和一的边,每次取一下\(min\)

暴力
#include <bits/stdc++.h>
#define LL long long
#define Re register int
#define LD double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(Re x = y; x <= z; x ++)
#define fp(x, y, z)for(Re x = y; x >= z; x ++)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')
#define WMX aiaiaiai~~
#define pr pair<int , int >
#define mk(x, y) makr_pair(x, y)
using namespace std;
namespace kiritokazuto{
    auto read = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}
/*
梦里海市云霞
梦外羽化成她
水中月镜中花
*/
/*
悄悄看了一眼T4
md
不可做
看到期望就发怵
*/
using namespace kiritokazuto;
int t;
int n, m;
const int maxn = 2e5 + 100, Inf = 20000000;//这玩意爆int
struct Node{
    int to, next, dis;
}wmx[maxn << 1];
//这不是昨天的二维dij吗?
//不建反图直接判?
//呃呃呃其实感觉王一昨天的枚举更diao来着
//内存好小啊
//还是枚举吧
//二维开不下
int head[maxn], len = 0;
fuc(void, Qian)(int from, int to, int dis){
    wmx[len].to = to;
    wmx[len].next = head[from];
    wmx[len].dis = dis;
    head[from] = len;
    len++;
}
int dis[maxn];
int ans;
deque <int> q;
random_device seed;
mt19937 rrand(seed());
//我把和1相连的全砍一遍
//强行更改最短路

/*
日
调了半天
记住是记住了成对变换从零开始
就是习惯打1.............
*/
int vis[maxn];
fuc(void, Spfa) (int x){
    fr(i, 1, n)vis[i] = 0;
    mes(dis, 33);
    q.push_front(x);
    vis[x] = 1;
    dis[x] = 0;
    while (!q.empty()){
        int top = q.front();
        q.pop_front();
        vis[top] = 0;
        for (Re i = head[top]; i; i = wmx[i].next){
            int to = wmx[i].to;
            int diss = wmx[i].dis;
            if (diss == -Inf){
                //  printf("KKKKKKKKKK to = %d\n", to);

                continue;
            }
            if (dis[to] > dis[top] + diss){
                dis[to] = dis[top] + diss;
                if (vis[to])continue;
                // q.push_back(to);
                if (rrand() & 1)q.push_back(to);
                else q.push_front(to);
                vis[to] = 1;
                // vis[to] = 1;
            }
        }
    }
    return;
}
fuc(void, init)(){
    ans = Inf;
    len = 0;
    // fr(i, 1, n)vis[i] = 0;
    // mes(dis, 33);
    //5558192971
    mes(head, 0);
}
signed main(){
    frein(leave);
    freout(leave);
    t = read();
    while (t--){
        n = read();
        m = read();
        init();
        // write(dis[1]);
        fr(i, 1, m){
            int x = read(), y = read(), z = read();
            Qian(x, y, z);
            Qian(y, x, z);
        }
        for (Re i = head[1]; i; i = wmx[i].next){
            int tmp = wmx[i].dis;
            int to = wmx[i].to;
            wmx[i].dis = wmx[i ^ 1].dis = -Inf;
            Spfa(to);
            ans = min(ans, dis[1] + tmp);
            // printf("to == %d \n", to);
            // fr(k, 1, n){
            //     printf("dis[%d] = %d \n", k, dis[k]);
            // }
            // ki;
            wmx[i].dis = wmx[i ^ 1].dis = tmp;
        }
        write((ans == Inf) ? -1 : ans);
        ki;
    }
    return 0;
}

熟练剖分

呃,还不太懂,先咕掉

std
#include <bits/stdc++.h>
#define LL long long
#define Re register int
#define LD double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(Re x = y; x <= z; x ++)
#define fp(x, y, z)for(Re x = y; x >= z; x ++)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')
#define WMX aiaiaiai~~
#define pr pair<int , int >
#define mk(x, y) makr_pair(x, y)
using namespace std;
namespace kiritokazuto{
    auto read = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}
/*

*/
using namespace kiritokazuto;
const int maxn = 3e3 + 10, Mod = 1e9 + 7;
const int Inf = 2147483647;
int rt, fa[maxn], sz[maxn];
LL ans, dp[maxn][maxn], g[maxn], h[maxn];
int n;
struct Node{
    int next, to;
}wmx[maxn << 1];
int head[maxn], len = 0;
fuc(void, Qian)(int from, int to){
    wmx[++len].to = to;
    wmx[len].next = head[from];
    head[from] = len;
}
fuc(LL, qpow)(LL x, LL y){
    LL res = 1;
    while (y){
        if (y & 1)res = (res * x) % Mod;
        x = (x * x) % Mod;
        y >>= 1;
    }
    return res % Mod;
}
fuc(void, dfs)(int x){
    sz[x] = 1;
    int cnt = 0;
    for (Re i = head[x]; i; i = wmx[i].next){
        int to = wmx[i].to;
        cnt++;
        dfs(to);
        sz[x] += sz[to];
    }
    int tot = qpow(cnt, Mod - 2);
    for (Re son = head[x]; son; son = wmx[son].next){
        fr(j, 0, n) g[j] = 1;
        for (Re st = head[x];st; st = wmx[st].next){
            fr(k, 0, sz[wmx[st].to] + 1){
                LL gk = g[k];
                if (k) gk -= g[k - 1];
                if (wmx[son].to == wmx[st].to){
                    LL fkg = dp[wmx[st].to][k];// dp[v][k]单点值
                    if (k) fkg -= dp[wmx[st].to][k - 1];
                    h[k] = (fkg * g[k] % Mod + dp[wmx[st].to][k] * gk % Mod - fkg * gk % Mod + Mod) % Mod;
                }
                else{
                    LL fk1 = dp[wmx[st].to][k - 1]; // dp[v][k-1]单点值
                    if (k > 1) fk1 -= dp[wmx[st].to][k - 2];
                    h[k] = (fk1 * g[k] % Mod + dp[wmx[st].to][k - 1] * gk % Mod - fk1 * gk % Mod + Mod) % Mod;
                    // u-v为轻边,到u为k即到v为k-1
                }
            }
            g[0] = h[0], h[0] = 0;
            fr(k, 1, sz[wmx[st].to] + 1) g[k] = (g[k - 1] + h[k]) % Mod, h[k] = 0;
        }
        for (Re j = sz[x]; j; --j) g[j] = (g[j] - g[j - 1] + Mod) % Mod;
        fr(j, 0, sz[x]) dp[x][j] = (dp[x][j] + g[j] * tot) % Mod;
    }
    if (!cnt) dp[x][0] = 1;
    fr(i, 1, sz[x] + 1) dp[x][i] = (dp[x][i] + dp[x][i - 1]) % Mod; // dp[u][i]为<=i的
}

signed main(){
    frein(tree);
    freout(tree);
    n = read();
    fr(i, 1, n){
        int x = read();
        fr(j, 1, x){
            int y = read();
            fa[y] = i;
            Qian(i, y);
        }
    }
    fr(i, 1, n){
        if (!fa[i]){
            rt = i;
            break;
        }
    }
    dfs(rt);
    fr(i, 1, n){
        ans = (ans + i * (dp[rt][i] - dp[rt][i - 1] + Mod) % Mod) % Mod;
    }
    write(ans);
    return 0;
}

下边是e...教练的题解

A. 简单的函数弱化版
直接线性筛即可,需要用辅助数组记录最小质因子的次幂数。

B. 那一天她离我而去
一个暴力的思路是,将所有与起点相连的边删除,从这些相连的点跑到其他相连点的最短路尝试更新答案。
可以尝试优化这个暴力思路。
发现这个算法有一部分冗余,我们可以分组进行最短路。
因为任意两个不同的点,二进制一定至少存在一位不同。
我们以每个二进制位的0,1进行分组,每组点组成的环一定被至少一次更新,于是可以达到目的。
复杂度 \(O(m log^2n)\)
请不要写 spfa,虽然测试数据中没有卡。

C. 熟练剖分(tree)
容易发现总方案数为所有节点的儿子个数的乘积。
可以计算每个时间代价的方案数是多少,最后算出总答案,除掉总方案数就是期望。
这个东西可以通过 dp 来计算,设 \(dp_{i,j}\) 表示节点 \(i\) 子树中最坏时间代价为 \(j\) 的方案数。
在归并子树的过程中,给 dp 数组多加一维,表示是否已经选择过重儿子即可。

标签:fr,LCIS,int,wmx,暑假,dis,集训,dp,define
From: https://www.cnblogs.com/kiritokazuto/p/16596982.html

相关文章

  • 国庆集训总结
    第一次感受到了提高组题目的魅力。题目分析这几次的题完全不像以前那样,会个模板稍加一些修改就A了,而是至少融合了两种不同的算法,一般需要想很久,思路自然就有了不同。如果......
  • 2022牛客国庆集训派对day6 A(极大矩阵计数)
    2022牛客国庆集训派对day6A(极大矩阵计数)A-All-oneMatrices_2022牛客国庆集训派对day6(nowcoder.com)题目求可以构成给出的01矩阵的全1极大矩阵数目思路悬线法可......
  • 2022牛客国庆集训派对day6 C 递归构造 归纳构造
    给出一个m你需要构造出来m个m维向量两两向量之间点乘为0向量每一维只能是1或-1保证m一定是2的幂次。直接构造出来那么大的显然不太可能发现不了什么比较好的规律。......
  • 2022牛客OI赛前集训营-提高组(第一场) 奇怪的函数 根号很好用
    奇怪的函数考虑暴力,每次查询\(O(n)\)扫所有操作,修改\(O(1)\)这启发我们平衡复杂度,考虑分块。观察题目性质,可以发现,经过若干次操作后得到的结果一定是一个关于\(x\)的分......
  • 2022牛客OI赛前集训营-提高组(第一场)
    教练给我们打的离线(数据分治忘删,多solve一次,明明复杂度O(n^3)偏偏不想压空间敬重桥廊不挂的话,70+100+50+50,挂了是70+100+0+0/cy懒得写题解。。。......
  • 作者解读ICML接收论文:如何使用不止一个数据集训练神经网络模型?
     Datawhale干货 作者:欧明锋,浙江大学导读:在实际的深度学习项目中,难免遇到多个相似数据集,这时一次仅用单个数据集训练模型,难免造成局限。是否存在利用多个数据集训练的可能......
  • 绍兴集训Day1
    BadLuckIsland题面翻译给三种人,分别是r,s,p个;在孤岛上,每两个不同种人相遇则互吃,r吃s,s吃p,p吃r求最后留下单一种族的概率题目描述TheBadLuckIslandisinhabit......
  • “科林明伦杯”哈尔滨理工大学暑假训练赛 F 题解
    题目内容传送门前置知识组合数乘法逆元Modularint模板题目分析分析输入与题意,本题关键即在推导有多少个不同数组的计算公式。设当前数组最大值为i,则有:\[ans_i......
  • 国庆集训
    简称国集Day3说实话今天做题时感觉就像昨天磕了药或者今天没吃药一样T1题目描述题目描述小A和小B都是51nod的用户。有一天小A打开了程序挑战排行榜,发现小......
  • P5934 [清华集训2012]最小生成树
    简要题意给你一个\(N\)个点,\(M\)条边的无向连通带权图。给定一条边\((u,v,L)\),请问需要在原图中删除多少条边,使得将\((u,v,L)\)插入图后,它既可能在最小生成树上,又......