CSP-S 33

10.17

t1

签到题

注意到约数只有 \(O(\sqrt n)\) 级别,暴力找约数即可。

唐人当然有唐做法啦!

分解质因数+dfs搜约数

反正唐就对了。

code

嘻嘻
#include <bits/stdc++.h>
#define int long long
#define pir pair<int, int>
using namespace std;
int n, m, cnt;
int a[210], ans[210];
int cntt[11], num[11];
map<int, int> mp;
pir node[3000000];

inline bool cmp(pir a, pir b) { return a.second < b.second; }

inline int km(int a, int b)
{
    int ans = 1;
    while (b)
    {
        if (b & 1)
            ans *= a;
        a *= a;
        b >>= 1;
    }
    return ans;
}

void dfs(int val, int id, int sum)
{
    if (sum > n)
        return;
    if (id == cntt[0] + 1)
    {
        if (sum > n)
            return;
        bool flag = 1;
        for (int i = 1; i <= cntt[0]; ++i)
            if (sum == num[i])
            {
                flag = 0;
                break;
            }
        if (flag && val % sum == 0)
            mp[sum]++;
        return;
    }
    for (int i = 0; i <= cntt[id]; ++i)
    {
        int nxt = km(num[id], i);
        if (nxt > n)
            return;
        dfs(val, id + 1, sum * nxt);
    }
}

inline void chai(int x)
{
    int val = x;
    cntt[0] = 0;
    for (int i = 2; i * i <= x; ++i)
    {
        if (x % i == 0)
        {
            mp[i]++;
            num[++cntt[0]] = i;
            while (x % i == 0)
                x /= i, ++cntt[cntt[0]];
        }
    }
    if (x != 1)
    {
        num[++cntt[0]] = x, cntt[cntt[0]] = 1;
        if (x <= n)
            mp[x]++;
    }
    int nnum = 1;
    dfs(val, 1, 1);
}

signed main()
{
    freopen("div.in","r",stdin);
    freopen("div.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= m; ++i)
        cin >> a[i], chai(a[i]);
    sort(a + 1, a + 1 + m);
    for (int pos = 1; pos <= m; ++pos)
    {
        if (a[pos] > n)
            break;
        if (mp[a[pos]])
            continue;
        mp[a[pos]]++;
        for (int i = pos + 1; i <= m; ++i)
            if (a[i] % a[pos] == 0)
                mp[a[pos]]++;
    }
    mp[1] = m;
    for (auto y : mp)
        node[++cnt] = y;

    ans[0] = n - cnt;
    for (int i = 1; i <= cnt; ++i)
        ans[node[i].second]++;
    for (int i = 0; i <= m; ++i)
        cout << ans[i] << "\n";
    return 0;
}

t2

第一眼:背包版题,第二眼:你值域开玩笑呢?

惊人注意力发现虽然值域很大,但答案很小,于是将 dp 数组的下标与所存内容交换,正常预处理 dp 后将其赋成前缀最小值,每次询问二分即可。

code

哈哈
#include <bits/stdc++.h>
using namespace std;
int n, m;
struct node
{
    int cst, val, tim;
} a[310];
int ans[310];
int dp[310][90010];

inline bool cmp(node a, node b) { return a.tim < b.tim; }

signed main()
{
    freopen("market.in", "r", stdin);
    freopen("market.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        cin >> a[i].cst >> a[i].val >> a[i].tim;
    sort(a + 1, a + 1 + n, cmp);

    memset(dp, 63, sizeof(dp));
    dp[0][0] = 0;
    int l = 1, r = 0;
    for (int k = 1; k <= 300; ++k)
    {
        while (r <= n && a[r].tim <= k)
            ++r;
        int lim = r - 1;
        for (int i = 0; i <= 90000; ++i)
            dp[k][i] = dp[k - 1][i];
        for (int i = l; i <= lim; ++i)
            for (int j = 90000; j >= a[i].val; --j)
                dp[k][j] = min(dp[k][j], dp[k][j - a[i].val] + a[i].cst);
        l = r;
    }

    for (int i = 1; i <= 300; ++i)
        for (int j = 90000; j; --j)
            if (dp[i][j + 1] < dp[i][j])
                dp[i][j] = dp[i][j + 1];

    int t, up;
    while (m--)
    {
        cin >> t >> up;
        int ans = upper_bound(dp[t], dp[t] + 1 + 90000, up) - dp[t];
        cout << ans - 1 << "\n";
    }
    return 0;
}

t3

神秘 dp

改不动了

喝的

详见QED代码

t4

赛时紧急打了个链(还是错的),喜提 8pts ,但是它输出 0 能有 37pts 你逗我呢???

听Wy_x 讲的不用线段树写法听懂了,但打的时候就是感觉不对,像 大分 一样,最后还是写了线段树。

我们将边权(边的归属权)下放,拆点,将每个点拆为两个,分别表示边的两种方向。

然后就一堆连边,find ,跳,判无解阿巴阿巴 。

实在不想写了,还是看代码吧。

code

呜呜
#include <bits/stdc++.h>
#define int long long
#define lid (id << 1)
#define rid (id << 1 | 1)
using namespace std;
const int mod = 1e9 + 7;
const int N = 3e5 + 10;
int n, m;
vector<int> e[N];
int Fa[N << 1];
int dep[N], siz[N], fa[N], son[N];
int top[N], tot, id[N], fid[N];
struct tree
{
    int l, r;
    bool flag;
} t[N << 3];
#define lid (id << 1)
#define rid (id << 1 | 1)

inline int km(int a, int b)
{
    int ans = 1;
    while (b)
    {
        if (b & 1)
            ans *= a, ans %= mod;
        a *= a, a %= mod;
        b >>= 1;
    }
    return ans;
}

inline int find(int x) { return x == Fa[x] ? x : Fa[x] = find(Fa[x]); }
inline void connect(int x, int y)
{
    int fx = find(x), fy = find(y);
    if (fx != fy)
        Fa[fx] = fy;
}

inline void merge(int u, int v, bool opt)
{
    if (opt)
        connect(u, v + n), connect(u + n, v);
    else
        connect(u, v), connect(u + n, v + n);
}

void dfs1(int x, int f)
{
    siz[x] = 1, fa[x] = f, dep[x] = dep[f] + 1;
    for (auto y : e[x])
    {
        if (y == f)
            continue;
        dfs1(y, x);
        siz[x] += siz[y];
        if (siz[y] > siz[son[x]])
            son[x] = y;
    }
}

void dfs2(int x, int t)
{
    top[x] = t;
    id[x] = ++tot;
    fid[tot] = x;
    if (!son[x])
        return;
    dfs2(son[x], t);
    for (auto y : e[x])
        if (y != fa[x] && y != son[x])
            dfs2(y, y);
}

inline int LCA(int u, int v)
{
    while (top[u] != top[v])
    {
        if (dep[top[u]] < dep[top[v]])
            swap(u, v);
        u = fa[top[u]];
    }
    return dep[u] < dep[v] ? u : v;
}

void build(int id, int l, int r)
{
    t[id].l = l, t[id].r = r;
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    build(lid, l, mid);
    build(rid, mid + 1, r);
}

void update(int id, int l, int r)
{
    if (l > r)
        return;
    if (t[id].flag)
        return;
    if (t[id].l == t[id].r)
    {
        merge(fa[fid[t[id].l]], fid[t[id].l], 0);
        t[id].flag = 1;
        return;
    }
    int mid = (t[id].l + t[id].r) >> 1;
    if (mid >= l)
        update(lid, l, r);
    if (mid < r)
        update(rid, l, r);
    t[id].flag = t[lid].flag & t[rid].flag;
}

signed main()
{
    freopen("usmjer.in","r",stdin);
    freopen("usmjer.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        Fa[i] = i, Fa[i + n] = i + n;
    for (int i = 1, u, v; i < n; ++i)
    {
        cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs1(1, 0);
    dfs2(1, 1);
    build(1, 1, n);
    int u, v;
    while (m--)
    {
        cin >> u >> v;
        int lca = LCA(u, v);
        if (u != lca && v != lca)
            merge(u, v, 1);
        while (top[u] != top[lca])
        {
            update(1, id[top[u]] + (fa[top[u]] == lca), id[u]);
            u = fa[top[u]];
        }
        update(1, id[lca] + 2, id[u]);
        while (top[v] != top[lca])
        {
            update(1, id[top[v]] + (fa[top[v]] == lca), id[v]);
            v = fa[top[v]];
        }
        update(1, id[lca] + 2, id[v]);
    }
    int tot = 0;
    for (int i = 2; i <= n; ++i)
    {
        int u = find(i), v = find(i + n);
        if (u == v)
        {
            cout << 0;
            return 0;
        }
        tot += (i != u) + (i + n != v);
    }
    cout << km(2, n - 1 - (tot >> 1)) << "\n";
    return 0;
}

不知道为什么感觉很累,大抵是被t4恶心到了。

累了累了,先歇会。

posted @ 2025-10-20 21:52  HS_fu3  阅读(13)  评论(0)    收藏  举报