2021牛客寒假算法基础集训营4【解题报告】

2022牛客寒假算法基础集训营1 A 九小时九个人九扇门 题意: 给定n个正整数,分别计算出数字根为1—9的组合数 涉及算法:数字根,线性dp 数字根: 将一正整数的各个位数相加(即横向相加)后,若加完后的值大于等于10的话,则继续将各位数进行横向相加直到其值小于十为止所得到的数,即为数字根。 性质一: 两个正整数相加,原来两个数的数字根之和等于和的数字根。 性质二: 设一个正整数为 x,则其数字根为 (x - 1) % 9 + 1。 由数字根的性质二,数字根求解的核心代码: int f (int x) { return (x - 1 阅读详情

A 九峰与签到题

题目描述

九峰正在准备一场毒瘤比赛,他是如此毒瘤以致于他想方设法降低通过率,他认为任意时间内通过率大于等于50%的题为签到题,现按照时间顺序给出整场比赛提交记录,请你输出哪些是签到题。

输入描述:

第一行输入两个整数m,n,表示提交记录个数和题目个数 ( m ≤ 1 0 5 , n ≤ 20 ) (m\leq 10^5,n\leq20) (m≤105,n≤20)
接下来m行,每行输入一个正整数 a i a_i ai​ 和一个字符串op,表示题目序号和评测结果 ( a i ≤ n , o p ϵ { ‘ ‘ A C " , ‘ ‘ U N A C " } ) (a_i\leq n,op \epsilon \{ ``AC",``UNAC"\}) (ai​≤n,opϵ{‘‘AC",‘‘UNAC"})

输出描述:

从小到大输出签到题的序号,按空格分割。若没有则输出-1。

分析:

签到题.

代码实现:

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

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)1e5;
const int N = (int)1e3;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)1e9 + 7;

int m, n;
int a[M + 5];
int b[M + 5];
bool vis[M + 5];

void work()
{
    scanf("%d %d", &m, &n);
    int x; char s[5];
    memset(vis, 1, sizeof(vis));
    for(int i = 1; i <= m; ++i)
    {
        scanf("%d %s", &x, s);
        if(s[0] == 'A') ++a[x];
        ++b[x];
        if(2 * a[x] < b[x])  vis[x] = 0;
    }
    bool f = 0;
    for(int i = 1; i <= n; ++i)
    {
        if(vis[i])  printf("%d ", i), f = 1;
    }
    if(!f)  printf("-1");
    printf("\n");

}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; scanf("%d", &T);
//    while(T--) work();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}

B 武辰延的字符串

题目描述

众所周知,武辰延很喜欢字符串。

这天,他对着两个字符串 s 和 t 发呆,他发现这两个串的前缀有很多相似的地方,s 的两个前缀连接起来竟也是 t 的前缀。

武辰延想知道有多少对 s 的非空前缀连接起来是 t 的前缀。

形式化地讲,我们把 s i s_i si​ 看作字符串 s 长度为 i 的前缀。

对于一对前缀 ( s i , s j ) (s_i,s_j) (si​,sj​) (允许 i=j)而言,当满足 s i + s j = t i + j s_i+s_j=t_{i+j} si​+sj​=ti+j​ 时,我们认为这两个 s 的前缀拼接后等于 t 的一个前缀。

两对 s 的前缀 ( s i , s j ) (s_i,s_j) (si​,sj​) 与 ( s i ′ , s j ′ ) (s_{i'},s_{j'}) (si′​,sj′​) 不同当且仅当 i ≠ i ′ i\neq i' i​=i′ 或 j ≠ j ′ j\neq j' j​=j′ 。

输入描述:

第一行一个字符串 s 。

第二行一个字符串 t 。

其中 1 ≤ ∣ s ∣ , ∣ t ∣ ≤ 1 e 5 1 \le \mid s\mid, \mid t\mid \le 1e5 1≤∣s∣,∣t∣≤1e5,只包含小写字母。

输出描述:

输出一行一个整数,表示满足条件的前缀的对数。

分析:

字符串Hash + 二分.

代码实现:

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

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)1e5;
const int N = (int)1e3;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)1e9 + 7;

int n, m;
char s[M + 5];
char t[M + 5];

struct Hash
{
    int base, mod;
    int n, p[M + 5], h[M + 5];

    void init(int _base, int _mod, int _n, char* s)
    {
        base = _base;
        mod = _mod;
        n = _n;
        p[0] = 1, h[0] = 0;
        for(int i = 1; i <= n; ++i)
        {
            p[i] = 1ll * p[i - 1] * base % mod;
            h[i] = (1ll * h[i - 1] * base + s[i] - 'a' + 1) % mod;
        }
    }

    int getH(int l, int r)
    {
        return ((h[r] - 1ll * h[l - 1] * p[r - l + 1]) % mod + mod) % mod;
    }
}h[4];

bool check(int i, int mid)
{
    int h0 = (1ll * h[0].getH(1, i) * h[0].p[mid] % h[0].mod + h[0].getH(1, mid)) % h[0].mod;
    int h1 = (1ll * h[1].getH(1, i) * h[1].p[mid] % h[1].mod + h[1].getH(1, mid)) % h[1].mod;
    int h2 = h[2].getH(1, i + mid);
    int h3 = h[3].getH(1, i + mid);
    return h0 == h2 && h1 == h3;
}

int cal(int i)
{
    int l = 0, r = max(0, min(n, m - i)), mid;
    while(l < r)
    {
        mid = (l + r + 1) >> 1;
        if(check(i, mid))    l = mid;
        else                 r = mid - 1;
    }
    return r;
}

void work()
{
    scanf("%s", s + 1);
    scanf("%s", t + 1);
    n = strlen(s + 1), m = strlen(t + 1);
    h[0].init(1331, (int)1e9 + 7, n, s); h[1].init(1331, (int)1e9 + 9, n, s);
    h[2].init(1331, (int)1e9 + 7, m, t); h[3].init(1331, (int)1e9 + 9, m, t);
    ll ans = 0;
    for(int i = 1; i <= n; ++i)
    {
        ans += cal(i);
    }
    printf("%lld\n", ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; scanf("%d", &T);
//    while(T--) work();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}

C 九峰与CFOP

大模拟,咕咕咕.

D 温澈滢的狗狗

题目描述

众所周知,温澈滢在宿舍养了一排 n 只狗狗,每只狗狗都有一个颜色 c i c_i ci​。同时,它们只喜欢和不同颜色的狗狗玩,否则它们会觉得很单调无趣。

也就是说,如果第 i 只狗狗和第 j 只狗狗颜色不同,那么它们可以拥有亲密关系,它们亲密度可以表示成 ∣ i − j ∣ \mid i-j\mid ∣i−j∣,否则它们就不能建立亲密关系。

当 n 只狗狗颜色两两不同时,它们有 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n−1)​ 对亲密关系;当 n 只狗狗的颜色完全一致时,它们之间就不存在任何一对亲密关系。

我们把这么多对亲密关系取出来,以亲密度为第一关键词,编号较小的狗狗的编号为第二关键词,编号较大的狗狗的编号为第三关键词排序(三维都按照升序排序)。

现在温澈滢想知道第 k 对亲密关系是哪一对狗狗,当然,必要的时候你可以告诉温澈滢这些狗狗之间不存在这么多的亲密关系。

输入描述:

第一行输入两个数字 n 和 k 。

第二行给出 n 个数字,第 i 个数字 c i c_i ci​ 表示第 i 只狗狗的颜色。

其中 1 ≤ n ≤ 1 e 51 ≤ n ≤ 1 e 5 , 1 ≤ k ≤ n ( n − 1 ) 2 1\le n\le 1e51≤n≤1e5 ,1\le k\le \frac{n(n-1)}{2} 1≤n≤1e51≤n≤1e5,1≤k≤2n(n−1)​

输出描述:

如果存在第 k 对狗狗,请在一行内输出两只狗狗的编号,小的在前,中间用一个空格隔开。

否则输出 -1 。

分析:

先二分出答案对应的亲密度, c a l ( m i d ) cal(mid) cal(mid) 表示亲密度 ≤ m i d \leq mid ≤mid 的对数,可以尺取求(异色对数 = 所有对数 - 同色对数).

得到答案对应的亲密度之后,再 O ( n ) O(n) O(n) 扫一遍即可.

代码实现:

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

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)1e5;
const int N = (int)1e2;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)998244353;

int n; ll k;
int c[M + 5];
int cnt[M + 5];

ll cal(int mid)
{
    ll ans = 0;
    for(int l = 1, r = 0; l <= n; ++l)
    {
        while(r < min(n, l + mid)) ++cnt[c[++r]];
        ans += min(mid, n - l) - cnt[c[l]] + 1;
        --cnt[c[l]];
    }
    return ans;
}

void work()
{
    scanf("%d %lld", &n, &k);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &c[i]);
    }
    int l = 1, r = n, mid;
    while(l < r)
    {
        mid = (l + r) >> 1;
        if(cal(mid) >= k)   r = mid;
        else                l = mid + 1;
    }
    if(r == n)
    {
        printf("-1\n");
        return;
    }
    k -= cal(r - 1);
    for(int i = 1; i + r <= n; ++i)
    {
        if(c[i] == c[i + r]) continue;
        if(!--k)
        {
            printf("%d %d\n", i, i + r);
            return;
        }
    }
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; cin >> T;
//    while(T--) work();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}

E 九峰与子序列

题目描述

学会字符串哈希后,动态规划选手九峰想要出一道解法为字符串哈希题,于是wcy给他口胡了一道题,却把九峰难倒了,你能帮他解决这个问题吗?
给定长度为n的字符串序列a和字符串k,询问a有多少子序列拼接起来等于k。

输入描述:

第一行输入一个正整数 n ( n ≤ 40 ) n(n\leq 40) n(n≤40)和字符串 k ( ∣ k ∣ ≤ 5 ∗ 1 0 6 ) k(|k|\leq 5*10^6) k(∣k∣≤5∗106)
第二行输入n个字符串 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1​,a2​,...,an​,表示给定序列
数据保证a中的字符串总长度不超过 5 ∗ 1 0 6 5*10^6 5∗106 ,输入的所有字符均为小写字母

输出描述:

一行输出一个整数,表示答案

分析:

思路一:

字符串哈希后直接爆搜是 O ( 2 40 ) O(2^{40}) O(240) 的.

考虑使用折半搜索,时间复杂度降到 O ( 2 20 ) O(2^{20}) O(220).

思路二:

设 f [ i ] [ j ] f[i][j] f[i][j] 表示前 i i i 个字符串匹配字符串 s s s 到位置 j j j 的方案数.

则有状态转移方程 f [ i ] [ j ] = f [ i − 1 ] [ j ] + [ t [ i ] = = s [ j − l e n [ i ] : j ] ] f [ i − 1 ] [ j − l e n [ i ] ] f[i][j] = f[i - 1][j] + [t[i] == s[j - len[i]:j]]f[i - 1][j - len[i]] f[i][j]=f[i−1][j]+[t[i]==s[j−len[i]:j]]f[i−1][j−len[i]].

PS:双模数哈希被卡常了,需要用自然溢出.

代码实现:

思路一:
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)5e6;
const int N = (int)1e3;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;

int n, m;
string k;
string s[40];
int sz[41];

int p[M + 5];
int mod = (int)1e9 + 7;
vector<int> h[41];

void init()
{
    sz[n] = k.size();
    p[0] = 1;
    for(int i = 1; i <= sz[n]; ++i)
    {
        p[i] = 1ll * p[i - 1] * 1331 % mod;
    }
    for(int i = 0; i < n; ++i)
    {
        sz[i] = s[i].size();
        h[i].resize(sz[i] + 1);
        for(int j = 1; j <= sz[i]; ++j)
        {
            h[i][j] = (1ll * h[i][j - 1] * 1331 + s[i][j - 1] - 'a' + 1) % mod;
        }
    }
    h[n].resize(sz[n] + 1);
    for(int j = 1; j <= sz[n]; ++j)
    {
        h[n][j] = (1ll * h[n][j - 1] * 1331 + k[j - 1] - 'a' + 1) % mod;
    }
}

int getH(int u, int l, int r)
{
    return ((h[u][r] - 1ll * h[u][l - 1] * p[r - l + 1]) % mod + mod) % mod;
}

int mp[2][M + 5];

void dfs1(int u, int len, int h0)
{
    if(u == m)
    {
        mp[0][len]++;
        return;
    }
    dfs1(u + 1, len, h0);
    if(len + sz[u] <= sz[n])
    {
        int h2 = (1ll * h0 * p[sz[u]] + getH(u, 1, sz[u])) % mod;
        if(h2 == getH(n, 1, len + sz[u]))
            dfs1(u + 1, len + sz[u], h2);
    }
}

ll quick(ll a, ll b, ll p)
{
    ll s = 1;
    while(b)
    {
        if(b & 1) s = s * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return s;
}

ll inv(ll n, ll p)
{
    return quick(n, p - 2, p);
}

ll ans = 0;

void dfs2(int u, int len, int h0)
{
    if(u == m - 1)
    {
        ans += mp[0][sz[n] - len];
        return;
    }
    dfs2(u - 1, len, h0);
    if(len + sz[u] <= sz[n])
    {
        int h2 = (1ll * getH(u, 1, sz[u]) * p[len] + h0) % mod;
        if(h2 == getH(n, sz[n] - (len + sz[u]) + 1, sz[n]))
            dfs2(u - 1, len + sz[u], h2);
    }
}

void work()
{
    cin >> n >> k;
    for(int i = 0; i < n; ++i) cin >> s[i];
    init();
    m = max(0, min(n, n / 2));
    dfs1(0, 0, 0);
    dfs2(n - 1, 0, 0);
    cout << ans << "\n";
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; scanf("%d", &T);
//    while(T--) work();
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}
思路二:
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)5e6;
const int N = (int)3e4;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)998244353;

int n;
char s[M + 5];
ll f[M + 5];

ull p[M + 5];
ull h[M + 5];

inline ull cal(const int& l, const int& r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}

void work()
{
    scanf("%d %s", &n, s + 1);
    int m = strlen(s + 1);
    p[0] = 1;
    for(int i = 1; i <= m; ++i)
    {
        p[i] = p[i - 1] * 131;
        h[i] = h[i - 1] * 131 + s[i] - 'a' + 1;
    }
    f[0] = 1;
    int sz; ull H;
    for(int i = 1; i <= n; ++i)
    {
        scanf("%s", s + 1); sz = strlen(s + 1);
        H = 0; for(int j = 1; j <= sz; ++j) H = H * 131 + s[j] - 'a' + 1;
        for(int j = m; j >= sz; --j)
        {
            if(cal(j - sz + 1, j) == H) f[j] += f[j - sz];
        }
    }
    printf("%lld\n", f[m]);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; scanf("%d", &T);
//    while(T--) work();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}

F 魏迟燕的自走棋

题目描述

众所周知,魏迟燕正带领着他的自走棋小队驰骋疆场。

自走棋这个游戏不需要过硬的操作能力,只需要搭配阵容并分配装备即可,非常适合魏迟燕这种手残党。

现在魏迟燕的小队中有 n 个人,仓库中有 m 件装备,每个人只能装备一件装备,每件装备只能分配给一个人。

其中,第 i 件装备可以给 k i k_i ki​ 个人中的一个,分别为 p 1 , ⋯   , p k i p_1,\cdots,p_{k_i} p1​,⋯,pki​​ ,获得的战力提升为 w i w_i wi​,总战力提升即为所有士兵战力提升之和。

魏迟燕想知道他能获得的最大总战力提升为多少?

输入描述:

第一行两个整数 n 和 m ,分别表示人数和装备数。

接下来 m 行,其中的第 i 行描述第 i 件装备的信息。

每行第一个整数 k i k_i ki​ 表示这件装备适用的人数,之后 k i k_i ki​ 个整数表示每个适用者的编号,最后一个整数 w i w_i wi​ 表示装备这件装备带来的战力提升。

其中 1 ≤ n , m ≤ 1 e 51 ≤ n , m ≤ 1 e 5 , 1 ≤ k i ≤ 2 1\le n,m\le 1e51≤n,m≤1e5,1\le k_i\le 2 1≤n,m≤1e51≤n,m≤1e5,1≤ki​≤2

输出描述:

一行输出一个整数表示能获得的最大战力提升。

分析:

首先对装备按照战力从大到小排序,然后贪心选择装备(能选就选).

由于 k k k 最大只有 2 2 2,所以这样做一定是最优的.

具体实现可以用并查集维护.

对于当前装备的两个人 a a a 和 b b b,则将 a a a 与 b b b 连边加入一个集合.

对于点数为 n n n,边数为 n − 1 n - 1 n−1 的集合,不难证明这 n n n 个人的任何一个人都可以当做未有装备的人.

对于点数为 n n n,边数为 n n n 的集合,则表示此集合已满.

详见代码.

代码实现:

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

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)1e5;
const int N = (int)1e2;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)998244353;

int n, m;
int fa[M + 5];
bool loop[M + 5];

struct node
{
    int k, p[2], w;
    bool operator<(const node& b)const
    {
        return w > b.w;
    }
} s[M + 5];

int tofind(int x)
{
    if(x == fa[x]) return x;
    return fa[x] = tofind(fa[x]);
}

void work()
{
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= m; ++i)
    {
        scanf("%d", &s[i].k);
        for(int j = 0; j < s[i].k; ++j) scanf("%d", &s[i].p[j]);
        scanf("%d", &s[i].w);
    }
    sort(s + 1, s + m + 1);
    for(int i = 1; i <= n; ++i) fa[i] = i, loop[i] = 0;
    ll ans = 0;
    for(int i = 1, a, b; i <= m; ++i)
    {
        if(s[i].k == 1)
        {
            a = tofind(s[i].p[0]);
            if(!loop[a])
            {
                loop[a] = 1;
                ans += s[i].w;
            }
        }
        else
        {
            a = tofind(s[i].p[0]), b = tofind(s[i].p[1]);
            if(a != b)
            {
                if(!loop[a] || !loop[b])
                {
                    fa[a] = b;
                    ans += s[i].w;
                    if(loop[a] || loop[b]) loop[b] = 1;
                }
            }
            else if(!loop[a])
            {
                loop[a] = 1;
                ans += s[i].w;
            }
        }
    }
    printf("%lld\n", ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; cin >> T;
//    while(T--) work();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}

G 九峰与蛇形填数

题目描述

蛇形填数是一道经典的入门题,但是九峰有自己的想法,他认为盘着的蛇不是一条好蛇,只有不断前进才能突破自我,变成真龙,因此,相比于将矩阵填数成回型(盘踞的蛇):

1 2 3 8 9 4 7 6 5 \begin{matrix} 1& 2 &3 \\ 8 & 9 &4 \\ 7 & 6 & 5 \end{matrix} 187​296​345​

九峰更喜欢将矩阵填成"S"型(行走的蛇):

1 2 3 6 5 4 7 8 9 \begin{matrix} 1 & 2 & 3 \\ 6 & 5 & 4 \\ 7 & 8 & 9 \end{matrix} 167​258​349​

现在给你一个n*n的初始全零的矩阵,请你将其按第二种方法填数,但是这样子太过简单,所以每一次操作九峰会选择一个子矩阵,请你在其子矩阵上进行填数,并在最后输出整个矩阵

输入描述:

第一行两个整数n,m,表示矩阵的大小和操作次数 ( n ≤ 2000 , m ≤ 3000 ) (n\leq 2000,m\leq 3000) (n≤2000,m≤3000)
接下来m行,每行输入三个正整数x,y,k,表示在以(x,y)为左上角,边长为k的方阵内填数 ( 1 ≤ x , y ≤ n , m a x ( x + k − 1 , y + k − 1 ) ≤ n ) (1\leq x,y \leq n,max(x+k-1,y+k-1)\leq n) (1≤x,y≤n,max(x+k−1,y+k−1)≤n)

输出描述:

输出一个 n ∗ n n*n n∗n的矩阵,表示最后的结果

分析:

上来写了一发线段树,结果 TLE(事实证明多交几发可以卡过去?

事实上,此题可以 O ( n ( n + m ) ) O(n(n + m)) O(n(n+m)) 解决.

枚举行,再倒序枚举操作,计算列的时候可以用并查集维护已填块.

详见代码.

代码实现:

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

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)2e3;
const int N = (int)3e3;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)998244353;

int n, m;
int a[M + 5][M + 5];
int x[N + 5], y[N + 5], k[N + 5];
int fa[M + 5];
int ans[M + 5];

int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch))
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

void print(int n)
{
    if(n < 0)
    {
        putchar('-');
        print(-n);
    }
    if(n > 9) print(n / 10);
    putchar(n % 10 + '0');
}

int tofind(int x)
{
    if(x == fa[x]) return x;
    return fa[x] = tofind(fa[x]);
}

void work()
{
    n = read(); m = read();
    for(int i = 1; i <= m; ++i) x[i] = read(), y[i] = read(), k[i] = read();
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= n; ++j) fa[j] = j, ans[j] = 0;
        for(int j = m; j >= 1; --j)
        {
            if(i < x[j] || i > x[j] + k[j] - 1) continue;
            for(int l = y[j]; l <= y[j] + k[j] - 1; ++l)
            {
                if(ans[l])
                {
                    l = tofind(l);
                }
                else
                {
                    if((i - x[j]) & 1) ans[l] = (i - x[j]) * k[j] + y[j] + k[j] - l;
                    else               ans[l] = (i - x[j]) * k[j] + l - y[j] + 1;
                    if(l > 1 && ans[l - 1])   fa[l - 1] = tofind(l);
                    if(l < n && ans[l + 1])   fa[l] = tofind(l + 1);
                }
            }
        }
        for(int j = 1; j <= n; ++j) print(ans[j]), putchar(j == n ? '\n' : ' ');
    }
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; cin >> T;
//    while(T--) work();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}

H 吴楚月的表达式

题目描述

众所周知,吴楚月在数据结构课的大作业环节选择了表达式求值。

他觉得实现一个线性的表达式求值太无聊了,于是他把问题丢到了一棵树上。

形式化地讲,这棵树有 n 个节点,1 号点为根,每个节点上都有一个权值 v i v_i vi​ ,代表参与运算的值。每条边都有一个 o p i op_i opi​ ,代表运算符。

于是树上一条路径变成了 v − o p − v − ⋯ − v − o p − v v-op-v-\cdots-v-op-v v−op−v−⋯−v−op−v 的形式,对应一个表达式。

吴楚月希望你对树上每一个节点 u ,计算出根到 u 的简单路径所对应的表达式的值。

由于计算结果可能很大,所以你需要对 1e9+7 取模 。

注:表达式优先级即正常的加减乘除的优先级,从左往右,乘除优先级高于加减。

输入描述:

第一行给出一个整数 n 表示节点个数。

第二行 n 个正整数,第 i 个数表示 i 号节点的权值 v i v_i vi​ 。

第三行 n-1 个正整数,第 i 个数 f a i fa_i fai​ 表示 i+1 号节点的父亲。

第四行一个长度为 n-1 的字符串, 第 i 个字符表示 i+1 号节点与它父亲之间连边对应的运算符。

其中 1 ≤ n ≤ 1 e 51 ≤ n ≤ 1 e 5 , 1 ≤ v i ≤ 1 e 9 , o p i ∈ { + , − , ∗ , / } 1\le n\le 1e51≤n≤1e5,1\le v_i \le 1e9, op_i\in\{+,-,*,/\} 1≤n≤1e51≤n≤1e5,1≤vi​≤1e9,opi​∈{+,−,∗,/}.

输出描述:

一行输出 n 个数字,其中第 i 个数字表示根到 i 号节点的路径所对应的表达式的值。

分析

直接模拟就好啦.

代码实现:

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

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)1e5;
const int N = (int)1e3;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)1e9 + 7;

int n, cnt;
int w[M + 5];
int head[M + 5];
struct node
{
    int v, nx;
} Edge[M * 2 + 5];

char op[M + 5];
ll f[M + 5];

void init()
{
    cnt = 0;
    for(int i = 1; i <= n; ++i)
    {
        head[i] = -1;
    }
}

void add(int u, int v)
{
    Edge[cnt].v = v;
    Edge[cnt].nx = head[u];
    head[u] = cnt++;
}

ll quick(ll a, ll b, ll p = mod)
{
    ll s = 1;
    while(b)
    {
        if(b & 1) s = s * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return s;
}

ll inv(ll n, ll p = mod)
{
    return quick(n, p - 2, p);
}

void dfs(int u, ll pre, ll cur)
{
//    printf("u = %d\n", u);
    for(int i = head[u]; ~i; i = Edge[i].nx)
    {
        int v = Edge[i].v;
        if(op[v] == '+')
        {
            f[v] = (pre + cur + w[v]) % mod;
            dfs(v, (pre + cur) % mod, w[v]);
        }
        else if(op[v] == '-')
        {
            f[v] = ((pre + cur - w[v]) % mod + mod) % mod;
            dfs(v, (pre + cur) % mod, (-w[v] % mod + mod) % mod);
        }
        else if(op[v] == '*')
        {
            f[v] = (pre + cur * w[v]) % mod;
            dfs(v, pre, cur * w[v] % mod);
        }
        else if(op[v] == '/')
        {
            f[v] = (pre + cur * inv(w[v])) % mod;
            dfs(v, pre, cur * inv(w[v]) % mod);
        }
    }
}

void work()
{
    scanf("%d", &n); init();
    for(int i = 1; i <= n; ++i) scanf("%d", &w[i]);
    for(int i = 2, fa; i <= n; ++i)
    {
        scanf("%d", &fa);
        add(fa, i);
    }
    scanf("%s", op + 2);
    f[1] = w[1];
    dfs(1, 0, w[1]);
    for(int i = 1; i <= n; ++i) printf("%lld%c", f[i], i == n ? '\n' : ' ');
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; scanf("%d", &T);
//    while(T--) work();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}

I 九峰与分割序列

题目描述

给出一个序列,将其分割成若干个子区间,子区间的贡献为:若前一个子区间的长度大于k且该区间长度小
于等于k,则贡献为区间和的两倍,否则贡献为区间和,求一种分割方法,使得所有子区间贡献之和最大,输出最大贡献。

输入描述:

第一行输入两个正整数n和k ( k ≤ n ≤ 1 0 5 ) (k\leq n\leq 10^5) (k≤n≤105)
第二行输入n个正整数 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1​,a2​,...,an​ (对于所有 1 ≤ i ≤ n , a i ≤ 1 0 9 1\leq i \leq n,a_i\leq 10^9 1≤i≤n,ai​≤109)

输出描述:

输出一个整数,表示最大贡献和

分析:

很明显这题 dp

设 f [ i ] [ 0 ] f[i][0] f[i][0] 表示考虑了前 i i i 个数,且第 i i i 个数所属子区间的长度小于等于 k k k.

\quad f [ i ] [ 1 ] f[i][1] f[i][1] 表示考虑了前 i i i 个数,且第 i i i 个数所属子区间的长度大于 k k k.

则有状态转移方程:

f [ i ] [ 0 ] = m a x { f [ j ] [ 0 ] + s [ i ] − s [ j ]        m a x ( 0 , i − k ) ≤ j ≤ i − 1 f [ j ] [ 1 ] + 2 s [ i ] − 2 s [ j ] m a x ( 0 , i − k ) ≤ j ≤ i − 1 f[i][0] = max \left\{ \begin{matrix} f[j][0] + s[i] - s[j] \;\;\; \qquad max(0, i - k) \leq j \leq i - 1 \\ f[j][1] + 2s[i] - 2s[j] \qquad max(0, i - k) \leq j \leq i - 1 \end{matrix} \right. f[i][0]=max{f[j][0]+s[i]−s[j]max(0,i−k)≤j≤i−1f[j][1]+2s[i]−2s[j]max(0,i−k)≤j≤i−1​

f [ i ] [ 1 ] = m a x { f [ j ] [ 0 ] + s [ i ] − s [ j ] 0 ≤ j ≤ i − k − 1 f [ j ] [ 1 ] + s [ i ] − s [ j ] 0 ≤ j ≤ i − k − 1 f[i][1] = max \left\{ \begin{matrix} f[j][0] + s[i] - s[j] \qquad 0 \leq j \leq i - k - 1 \\ f[j][1] + s[i] - s[j] \qquad 0 \leq j \leq i - k - 1 \end{matrix} \right. f[i][1]=max{f[j][0]+s[i]−s[j]0≤j≤i−k−1f[j][1]+s[i]−s[j]0≤j≤i−k−1​

用 3 3 3 颗线段树分别维护 f [ j ] [ 0 ] − s [ j ] , f [ j ] [ 1 ] − 2 s [ j ] , f [ j ] [ 1 ] − s [ j ] f[j][0] - s[j], f[j][1] - 2s[j], f[j][1] - s[j] f[j][0]−s[j],f[j][1]−2s[j],f[j][1]−s[j] 的区间最大值即可.

代码实现:

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

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)1e5;
const int N = (int)1e3;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)1e9 + 7;

int n, k;
ll s[M + 5];
ll f[M + 5][2];

struct node
{
    ll mx;
} tree[3][M * 4 + 5];

inline int lc(int k) {return k<<1;}
inline int rc(int k) {return k<<1|1;}

void push_up(int p, int k)
{
    tree[p][k].mx = max(tree[p][lc(k)].mx, tree[p][rc(k)].mx);
}

void build(int p, int k, int l, int r)
{
    if(l == r)
    {
        tree[p][k].mx = -inf;
        return;
    }
    int mid = (l + r) >> 1;
    build(p, lc(k), l, mid);
    build(p, rc(k), mid + 1, r);
    push_up(p, k);
}

void update(int p, int k, int l, int r, int a, ll b)
{
    if(l == r)
    {
        tree[p][k].mx = b;
        return;
    }
    int mid = (l + r) >> 1;
    if(a <= mid)    update(p, lc(k), l, mid, a, b);
    else            update(p, rc(k), mid + 1, r, a, b);
    push_up(p, k);
}

ll query(int p, int k, int l, int r, int a, int b)
{
    if(l >= a && r <= b)    return tree[p][k].mx;
    int mid = (l + r) >> 1; ll mx = -inf;
    if(a <= mid)    mx = max(mx, query(p, lc(k), l, mid, a, b));
    if(mid < b)     mx = max(mx, query(p, rc(k), mid + 1, r, a, b));
    return mx;
}

void work()
{
    scanf("%d %d", &n, &k);
    for(int i = 1; i <= n; ++i) scanf("%lld", &s[i]), s[i] += s[i - 1];
    build(0, 1, 1, n); build(1, 1, 1, n); build(2, 1, 1, n);
    memset(f, -inf, sizeof(f));
    f[1][0] = s[1]; update(0, 1, 1, n, 1, f[1][0] - s[1]);
    for(int i = 2; i <= n; ++i)
    {
        f[i][0] = max(f[i][0],     s[i] + query(0, 1, 1, n, max(1, i - k), i - 1));
        f[i][0] = max(f[i][0], 2 * s[i] + query(2, 1, 1, n, max(1, i - k), i - 1));
        if(i == k)     f[i][0] = max(f[i][0], s[i]);
        if(i - k - 1 >= 1)  f[i][1] = max(f[i][1], s[i] +
                                          max(query(0, 1, 1, n, 1, i - k - 1),
                                              query(1, 1, 1, n, 1, i - k - 1)));
        if(i == k + 1)  f[i][1] = max(f[i][1], s[i]);

//        printf("f[%d][0] = %lld\tf[%d][1] = %lld\n", i, f[i][0], i, f[i][1]);

        update(0, 1, 1, n, i, f[i][0] - s[i]);
        update(1, 1, 1, n, i, f[i][1] - s[i]);
        update(2, 1, 1, n, i, f[i][1] - 2 * s[i]);
    }
    printf("%lld\n", max(f[n][0], f[n][1]));
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; scanf("%d", &T);
//    while(T--) work();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}

J 邬澄瑶的公约数

题目描述

众所周知,邬澄瑶正在学习欧几里得算法。

现在她已经可以轻松求解 gcd ⁡ ( x 1 , ⋯   , x n ) \gcd(x_1,\cdots,x_n) gcd(x1​,⋯,xn​),并为此洋洋得意。为了整治狂妄自大的邬澄瑶,她的室友把 gcd ⁡ ( x 1 p 1 , ⋯   , x n p n ) \gcd(x_1^{p_1},\cdots,x_n^{p_n}) gcd(x1p1​​,⋯,xnpn​​) 这个式子甩给了他。

邬澄瑶被难住了,只好来求助于你,希望你帮她求出这个式子。

由于结果可能很大,你需要对 1e9+7 取模。

特别地,邬澄瑶的室友认为 gcd ⁡ ( x ) = x \gcd(x) = x gcd(x)=x。

输入描述:

第一行一个数表示 n 。

第二行 n 个数,第 i 个数表示 x i x_i xi​ 。

第三行 n 个数,第 i 个数表示 p i p_i pi​ 。

其中, 1 ≤ n , x i , p i ≤ 1 e 4 1\le n,x_i,p_i\le1e4 1≤n,xi​,pi​≤1e4。

输出描述:

输出一行一个数表示答案。

分析:

把每个 x i x_i xi​ 分解质因数,乘 p i p_i pi​ 再取 min 即可.

代码实现:

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

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const int M = (int)1e5;
const int N = (int)1e3;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
const ll mod = (ll)1e9 + 7;

bool is_prime[M + 5];
int prime[M + 5], cnt;

void init()
{
    memset(is_prime, 1, sizeof(is_prime));
    is_prime[0] = is_prime[1] = 0;
    for(int i = 2; i <= M; ++i)
    {
        if(is_prime[i])
        {
            prime[++cnt] = i;
        }
        for(int j = 1; j <= cnt && i * prime[j] <= M; ++j)
        {
            is_prime[i * prime[j]] = 0;
            if(i % prime[j] == 0)
            {
                break;
            }
        }
    }
}

int n;
int x[M + 5];
int p[M + 5];

int mp[M + 5];
int v[M + 5];

void divide(int x, int p)
{
    for(int i = 1; i <= cnt; ++i) v[i] = 0;

    for(int i = 1; i <= cnt && 1ll * prime[i] * prime[i] <= x; ++i)
    {
        if(x % prime[i] == 0)
        {
            int c = 0;
            while(x % prime[i] == 0)
            {
                ++c;
                x /= prime[i];
            }
            v[i] = c * p;
        }
    }
    if(x > 1) v[lower_bound(prime + 1, prime + cnt + 1, x) - prime] = p;

    for(int i = 1; i <= cnt; ++i) mp[i] = min(mp[i], v[i]);
}

ll quick(ll a, ll b, ll p = mod)
{
    ll s = 1;
    while(b)
    {
        if(b & 1) s = s * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return s;
}

void work()
{
    memset(mp, inf, sizeof(mp));
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) scanf("%d", &x[i]);
    for(int i = 1; i <= n; ++i) scanf("%d", &p[i]);
    for(int i = 1; i <= n; ++i) divide(x[i], p[i]);
    ll ans = 1;
    for(int i = 1; i <= cnt; ++i) ans = ans * quick(prime[i], mp[i]) % mod;
    printf("%lld\n", ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; scanf("%d", &T);
//    while(T--) work();
    init();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}
2021牛客寒假算法基础集训营2 J.牛牛想要成为hacker 2021牛客寒假算法基础集训营2 J.牛牛想要成为hacker 题目描述 在算法竞赛中"hack"一般指用一组测试数据触发程序的缺陷,从而导致本来通过题目的 AC 代码无法通过该测试数据。 一般情况见得比较多的是用 hack 数据导致别人 WA 掉,当然也有一些会导致原本的 AC 代码 TLE 和 MLE。 牛牛在一些简单的练习题时遇到了这样一个问题。 给定一个大小为 nnn 的数组 a(1≤ai≤109)a(1 \leq a_i \leq 10^9)a(1≤ai​≤109),然后请你判断数组元素是否能够从 阅读详情

相关推荐

告别手动标注!PDMS NakiToolkit插件安装与初体验:以Pipeline工具为例

本文详细介绍了PDMS NakiToolkit插件的安装与使用,特别是其Pipeline工具如何通过自动化标注和材料统计功能大幅提升三维工厂设计效率。从环境准备到实战演示,帮助工程师告别繁琐的手动标注工作,实现项目交付周期的大幅缩短。

weixin_30047059的博客 351

11.21刷题日记

动态规划 :牛客NC2 不相邻取数 1、描述:小红拿到了一个数组。她想取一些不相邻的数,使得取出来的数之和尽可能大。你能帮帮她吗? 思路: 用dp数组表示取前i个数时所达到的和最大值,依据题意可轻松获得状态转移方程: dp[i]=max(dp[i-1],dp[i-2]+num[i]) 代码: n = int(input()) num = list(map(int, input().split(' '))) dp = [0]*(len(num)+1) dp[1] = num[0] for i in range

weixin_44431508的博客 2263

自定义LayoutManager实现android-pile-layout滑动卡片堆叠效果

这是我的第一篇博客,总算有个契机开始写博客了,就从自定义LayoutManager开始吧。 前段时间看到一个项目(android-pile-layout),效果特别不错,这是效果图: 效果确实不错,我看了下实现,是用的自定义的ViewGroup实现的,计算什么还搞的挺复杂的,具体的没细看。作者说也尝试过用LayoutManager实现,但是没找到合适的数学模型,好吧,看到数学模型我

u014296305的博客 1万+

C++语言篇 字符串及字符数组练习

string 的应用举例 1、读程序,写结果: #include &lt;bits/stdc++.h&gt; using namespace std; int main(){ //1.string类重载运算符operator&gt;&gt;用于输入, //同样重载运算符operator&lt;&lt;用于输出操作 string str1; ...

流年的博客 9598

字节跳动程序媛教你如何刷算法题:面试手撕代码我就没怕过

本人上一次刷题还是大一的C语言期末考试……但是面试中算法考核截止上岸前一直保持着100%正确率的光辉记录。 本文将给你指明一条刷题的决胜指南。并从算法的重要性、题库的选择以及刷题的三大步骤分别进行讲解,彻底解决你所有关于面试算法所有的困扰。

Stay Hungry Stay Foolish 求知若饥 虚心若愚 2万+

【CUT&TAG分析-加了spike in的样品】

使用 Bowtie2 或 Subread (subjunc) 来构建大肠杆菌的索引。bowtie2比对时设置参数–local, 局部比对。

weixin_57975238的博客 1400

每日总结(2022/2/8)

每日总结

weixin_62494553的博客 518

1006. 换个格式输出整数 (15)-PAT乙级真题

1006. 换个格式输出整数 (15)让我们用字母B来表示“百”、字母S表示“十”,用“12…n”来表示个位数字n(&lt;10),换个格式来输出任一个不超过3位的正整数。例如234应该被输出为BBSSS1234,因为它有2个“百”、3个“十”、以及个位的4。输入格式:每个测试输入包含1个测试用例,给出正整数n(&lt;1000)。输出格式:每个测试用例的输出占一行,用规定的格式输出n。输入样例1...

柳婼 の blog 2243

(算法)两数之和

题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。 思路 创建一个空哈希表 遍历数组,查看target与当前元素的差是否在哈希表中。 若不存在,则将当前元素以key的形式存入哈希表,值为当前元素的索引值 若存在,则直接返回当前元素的索引值和哈希表中存在的元素的索引值 var twoSu

Dax1_的博客 418

MS1861宏晶微视频显示与控制器芯片:开发资料全解析与应用指南

本文全面解析了宏晶微MS1861视频显示与控制器芯片的核心功能与开发流程。该芯片作为高性能的“视频信号翻译官”,支持HDMI、LVDS等多种输入与MIPI、LVDS等输出,集成强大的图像处理与OSD叠加功能。文章详细介绍了从资料获取、环境搭建到以HDMI转MIPI为例的实战配置与调试技巧,为工业HMI、广告机等应用的开发者提供了完整的应用指南。

weixin_29198045的博客 338

CDD数据库文件制作(二)——DTC配置

1.DTC库 2.新建DTC DTC相关介绍:https://blog.youkuaiyun.com/LOVE135149/article/details/122565443 ① 选择DTC数据库 ② 点击新建DTC ③ DTC参数编辑 3.将DTC库中的DTC加载到Variant中 找到Fault Memory的DTC Table,鼠标放在DTC Table区域,右键点击选择Copy … Reference from Available DTCs…,即可将DTC库中的故障码加载至Variant中。 虽然选择Co

LOVE135149的博客 1万+

2021牛客寒假算法基础集训营4 A.九峰与签到题(签到)

A.九峰与签到题 题目链接:https://ac.nowcoder.com/acm/contest/9984/A 题目描述: 九峰正在准备一场毒瘤比赛,他是如此毒瘤以致于他想方设法降低通过率,他认为任意时间内通过率大于等于50%的题为签到题,现按照时间顺序给出整场比赛提交记录,请你输出哪些是签到题。 输入描述: 第一行输入两个整数m,n,表示提交记录个数和题目个数(m≤10^5,n≤20) 接下来m行,每行输入一个正整数ai 和一个字符串op,表示题目序号和评测结果(ai≤n,opϵ{‘‘AC",‘‘UN

马克菠萝包ଲ的博客 273

【unity实战】完美的2D横版平台跳跃玩家控制器,使用InputSystem+有限状态机实现人物加速减速 多段跳 长短跳 多段攻击 冲锋 冲锋残影 滑墙 蹬墙跳 滑墙 土狼时间 预输入 攀爬 爬楼梯

【unity实战】使用unity的新输入系统InputSystem+有限状态机设计一个玩家状态机控制——实现玩家的待机 移动 闪避 连击 受击 死亡状态切换这次来实现一个2d平台平台跳跃玩家控制器,平台人物控制要做的好,要考虑的问题会有很多,比如移动加速减速 多段跳 冲锋 冲锋残影 滑墙 蹬墙跳 土狼时间 预输入 攀爬 爬楼梯//减速至于为什么叫这个名字(土狼时间)呢?其实这个名词来自于华纳兄弟动画公司,一部古老的动画系列影片《Looney Tunes》

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 6044

【解题报告】2021牛客寒假算法基础集训营4

【解题报告】2021牛客寒假算法基础集训营4前面的话A :九峰与签到题 | 模拟 (签到题)B: 武辰延的字符串 | exKMPD :温澈滢的狗狗 | 二分E: 九峰与子序列 | dpdpdp + 字符串哈希F: 魏迟燕的自走棋 | 并查集G:九峰与蛇形填数 | 差分 + 优先队列H:吴楚月的表达式 | 树形 dpdpdpI:九峰与分割序列 | dpdpdp + 单调队列优化J:邬澄瑶的公约数 | 数论参考 前面的话 比赛连接:2021牛客寒假算法基础集训营4 有些题目是自己思考做出来的,有些是看他人的

溢流眼泪的博客 1336

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

2025牛客寒假算法基础集训营4

1.首尾相同,val为2^(cnt-2)*(n-2)*2(理解为首尾是00和11两个情况所以乘2)2.首尾不同,val为2^(cnt-2)*2*2,所以总和为2^(cnt-1)*n,和三相同可以合并。’ 的个数为 p,显然将每个 ‘?思路:ai有n种情况,ai-1有m种情况,总共有n*m种,期望的和就是和的期望,所以将得到的不同的| ai-ai-1|的值相加再除以n*m,分出如下图三个部分,其中两个部分可以直接用等差求出,还有一个部分可以发现横竖可以构成两个相等的等差,如0 1 2 3 0 1 2 3。

2501_90365146的博客 1736

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

2024牛客寒假算法基础训练营4

2024牛客寒假营4【ABCDEGFHIK】

weixin_73603271的博客 1699

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

2025牛客寒假算法基础集训营4题解

2025牛客寒假算法基础集训营4题解

FZANOTFOUND的博客 2133

2020牛客寒假算法基础集训营1 解题报告 Apare_xzc

2020牛客寒假算法基础集训营1 解题报告 Apare_xzc 比赛链接:2020牛客寒假算法基础集训营1<– 2020-02-04 13:00:00 至 2020-02-04 18:00:00 时长: 5小时 已有3952人报名 官方题解:【题解】牛客寒假集训营第一场 <– A. honoka和格点三角形 题目链接 分析:     &...

Apare_xzc的博客 2943

2025牛客寒假算法基础集训营5

当下了三次时,此时棋盘还有三个空,因为小L可以一次下两个(这样做是最聪明的办法,赢的几率越大),那就判断鸡下在三个位置中任意一个,看小L可不可以赢;当下了四次,还有一个,小L占了,判断能不能赢。当x不断的开方,一定会变为1,y的话可以不断的平方,直到x乘2^n在可以经过无数次开方得到y的范围内,所以只要不是x和y里面只有一个是0的话,都可以转变。小L踩一下油门,速度会瞬间提升 10m/s,踩一下刹车,速度会瞬间降低 5m/s,踩一下离合,在踩离合这一过程中速度降低 10m/s,1s之后恢复原速。

2501_90365146的博客 1625

2025牛客寒假算法基础集训营6

字符,将其同时删去,剩余字符按原顺序拼接起来。形式化地,变鸡器选择两个下标 i,j(i<j)满足 si≠sj​,将这两个字符同时删去,剩余字符串拼接在一起得到s1s2⋯si−1si+1⋯sj−1sj+1⋯sn现在,小火想知道,对于给定的字符串 s,他能否通过变鸡器将该字符串变为 "CHICKEN"例如 (1,4),(3,5),(3,5),(7,5)是合法的,而 (1,2),(1,1)不是。这是因为在到达相同分数的情况下,我们只关心最小代价的路径,这样可以减少后续不必要的计算,将去重后的状态存储到。

2501_90365146的博客 1760

【解题报告】2022牛客寒假算法基础集训营1

【解题报告】2022牛客寒假算法基础集训营1A:九小时九个人九扇门题意 | 简单思路 | 数学 + dp代码B:炸鸡块君与FIFA22题意 | 中等思路 | 数据结构 + 简单同余代码C:Baby's first attempt on CPU题意 | 简单思路 | 简单dp代码D:牛牛做数论题意 | 中等思路 | 数论代码E:炸鸡块君的高中回忆F:中位数切分题意 | 中等思路 | 数据结构 + dp代码G:ACM is all you need题意 | 中偏难思路 | 思维 + 差分代码H:牛牛看云题意 |

溢流眼泪的博客 1202

2020牛客寒假算法基础集训营5 题目及解析

传送门:2020牛客寒假算法基础集训营5 由于是个人总结向,所以有点精简,而且可能和官方的标程截然不同,当然如果有什么疑问可以留言或者私信交流。 文章目录A. 模板B. 牛牛战队的比赛地C. C语言IDED. 牛牛与牛妹的约会E. Enjoy the gameF. 碎碎念H. HashI. I题是个签到题J. 牛牛战队的秀场 A. 模板 思路: 签到题吧,名字起的吓人,楞是先交了...

放荡者的茶会 1654

2020牛客寒假算法基础集训营4 题目及解析

传送门:2020牛客寒假算法基础集训营4 剩下两题没做,等有时间补补。 文章目录A. 欧几里得B. 括号序列C. hanayo和米饭D. 子段异或E. 最小表达式F. 树上博弈G. 音乐鉴赏H. 坐火车 A. 欧几里得 思路: 签到题吧,随便打表看n=0-5的情况,可以明显发现跟fib有关。 代码如下: #include<bits/stdc++.h> #define IOS ...

放荡者的茶会 3983

2020牛客寒假算法基础集训营6 题目及解析

传送门:2020牛客寒假算法基础集训营1 题目及解析 传送门:2020牛客寒假算法基础集训营4 题目及解析 传送门:2020牛客寒假算法基础集训营5 题目及解析 传送门:2020牛客寒假算法基础集训营6 题目及解析 由于是个人总结向,所以有点精简,而且可能和官方的标程截然不同,当然如果有什么疑问可以留言或者私信交流。 文章目录A. 配对B. 图C. 汉诺塔D. 重排列 A. 配对...

放荡者的茶会 1502

2024牛客寒假算法基础训练营1

2024牛客寒假营1【ABCGLMEFI】

weixin_73603271的博客 1222

【解题报告】2021牛客寒假算法基础集训营 6

【解题报告】2021牛客寒假算法基础集训营 6前面的话A\mathfrak{A}A :回文括号序列计数 | QD思维B\mathfrak{B}B :系数 | 数学C\mathfrak{C}C : 末三位 | QD数学D\mathfrak{D}D : 划数 | QD数学E\mathfrak{E}E :网格 | dpdpdpF\mathfrak{F}F :组合数问题 | 数学 + 打表G\mathfrak{G}G : 机器人 | 状压 dpdpdp + 高精度H\mathfrak{H}H :动态最小生成树I\m

溢流眼泪的博客 426
上一篇: 2021牛客寒假算法基础集训营3【解题报告】
下一篇: 2021牛客寒假算法基础集训营5【解题报告】
The___Flash
博客等级 码龄8年 79粉丝 223原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值