2022NOIPA层联测11

整场考试都被我拿来死磕T3了,以为它是树形dp,结果没开long long连暴力的15都没拿到。。听说考前爆0可以涨rp,不知道是不是真的。。

In the dark days, do not let the cold fate of secretly pleased; fate since to abuse us, we should use the attitude of retaliation.
– Shakespeare

在灰暗的日子中,不要让冷酷的命运窃喜;命运既然来凌辱我们,我们就应该用处之泰然的态度予以报复。
– 莎士比亚

 

A. 小 h 的几何

“熟知”九点圆圆心是外心O和垂心H的中点……我连九点圆是什么都没听说过……那个向量公式大概学过:

然后正弦和余弦都是库函数,对于每种情况不用枚举i,j,k,求一下和记录贡献的次数就好,固定一个剩下的任选就是C(n-1, 2),这东西cr好像给我讲过一次,我又听她讲了一遍。。

code
#include <bits/stdc++.h>

using namespace std;

typedef long double ll;
const int maxn = 5e5 + 3;
const ll B = 1e9, PI = 3.1415926535;

int n, p[maxn];
ll ls[maxn], rs[maxn], sx, sy;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    freopen("geometry.in", "r", stdin);
    freopen("geometry.out", "w", stdout);
    
    n = read();
    for(int i=1; i<=n; i++)
    {
        int q = read();
        ls[i] = cos((ll)q/B*PI); rs[i] = sin((ll)q/B*PI);
    }
    for(int i=1; i<=n; i++)
    {
        sx += ls[i]; sy += rs[i];
    }
    printf("%.15Lf %.15Lf\n", sx*1.5/n, sy*1.5/n);

    return 0;
}

 

B. 小w 的代数

子链概念里的那个路径包含就可以不是只能包含,审对题之后发现连暴力都不会了。。

%%%%%351238 以下代码是鹤的 部分分55:链条树:除了空集什么都能选;菊花树:最多只有两个点能被同时选上,要求大小关系就可以写成等差数列求和的形式;小数据:带撤销形式回溯的dfs,hash一下重复情况;普通的树:用树形dp的形式累计一下答案的个数。

code
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int maxn = 555;
const int mod = 998244353;
const ull B = 233;

int n, m, top, fa[maxn], v[maxn], dd[maxn], stk[maxn];
ll ans, f[maxn];
ull hs[maxn];
unordered_map<ull, bool> mp;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

ll qpow(ll a, ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}

struct node 
{
    int next, to;
}a[maxn<<1];
int head[maxn], len;

void add(int x, int y)
{
    a[++len].to = y; a[len].next = head[x];
    head[x] = len;
}

void dfs(int x, int dad)
{
    for(int i=head[x]; i; i=a[i].next)
    {
        int kid = a[i].to;
        if(kid == dad) continue;
        fa[kid] = x;
        dfs(kid, x);
    }
}

void dfss(int x, int dad)
{
    f[x] = 1; dd[x] = dad;
    for(int i=head[x]; i; i=a[i].next)
    {
        int kid = a[i].to;
        if(kid == dad) continue;
        dfss(kid, x);
    }
}

void work(int x, int dad)
{
    for(int i=head[x]; i; i=a[i].next)
    {
        int kid = a[i].to;
        if(kid == dad) continue;
        work(kid, x);
    }
    int now = dd[x];
    while(now)
    {
        if(x > now) {f[now] += f[x]; f[now] %= mod;}
        now = dd[now];
    }
}

void dfs2(int x, int dad)
{
    if(!mp[hs[top]]) mp[hs[top]] = 1, ans = ans+1>=mod ? ans+1-mod : ans+1;
    v[x] = 1;
    for(int i=head[x]; i; i=a[i].next)
    {
        int kid = a[i].to;
        if(v[kid]) continue;
        if(kid > stk[top] && !v[kid])
        {
            ull h = hs[top];
            stk[++top] = kid;
            hs[top] = hs[top-1]*B+kid;
            dfs2(kid, x);
            hs[--top] = h;
        }
        dfs2(kid, x);
    }
    v[x] = 0;
}

int main()
{
    freopen("algebra.in", "r", stdin);
    freopen("algebra.out", "w", stdout);
    
    n = read(); m = read();
    for(int i=1; i<=m; i++)
    {
        int x = read(), y = read();
        add(x, y); add(y, x);
    }
    if(m == n-1)
    {
        dfs(1, 0);
        int sp1 = 0, sp2 = 0;
        for(int i=2; i<=n; i++)
        {
            if(fa[i] != i-1) sp1 = 1;
            if(fa[i] != 1) sp2 = 1;
        }
        if(!sp1) {printf("%lld\n", qpow(2,n)-1); exit(0);}
        if(!sp2) {printf("%lld\n", (1ll*n*n%mod+n)%mod*qpow(2,mod-2)%mod); exit(0);}
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++) f[j] = 0;
            dfss(i, 0);
            work(i, 0);
            ans += f[i]; while(ans >= mod) ans -= mod;
        }
        printf("%lld\n", ans);
    }
    if(n <= 50)
    {
        for(int i=1; i<=n; i++)
        {
            hs[1] = i;
            top = 0; stk[++top] = i;
            dfs2(i, 0);
        }
        printf("%lld\n", ans);
    }

    return 0;
}

 

C. 小y 的数论

对于这么一个鬼畜,我是怎么以为它很水的!?是因为眼熟的斯坦纳树吗……

TLE 15
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 3e5 + 3;

int Max, q, l, r, n, k;
int dep[maxn], fa[maxn], siz[maxn], top[maxn], son[maxn];
ll val[maxn], ans;
bool vis[maxn]; 
vector<int> ext;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int next, to, w;
}a[maxn<<1];
int head[maxn], len;

void add(int x, int y, int w)
{
    a[++len].to = y; a[len].next = head[x]; a[len].w = w;
    head[x] = len;
}

int count(int x)
{
    int res = 0;
    while(x)
    {
        x -= (x & -x);
        res++;
    }
    return res;
}

void find_heavy_edge(int u, int fat, int depth)
{
    siz[u] = 1;
    dep[u] = depth;
    fa[u] = fat;
    son[u] = 0;
    int maxsize = 0;
    for(int i=head[u]; i; i=a[i].next)
    {
        int v = a[i].to;
        if(dep[v]) continue;
        find_heavy_edge(v, u, depth+1);
        siz[u] += siz[v];
        if(siz[v] > maxsize)
        {
            maxsize = siz[v];
            son[u] = v;
        }
    }
}

void connect_heavy_edge(int u, int ancestor)
{
    top[u] = ancestor;
    if(son[u])
    {
        connect_heavy_edge(son[u], ancestor);
    }
    for(int i=head[u]; i; i=a[i].next)
    {
        int v = a[i].to;
        if(v == fa[u] || v == son[u]) continue;
        connect_heavy_edge(v, v);
    }
}

int LCA(int x, int y)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]]) swap(x, y);
        x = fa[top[x]];
    }
    if(dep[x] > dep[y]) swap(x, y);
    return x;
}

void dfs(int u, int fa, int w)
{
    if(vis[u]) val[u] = w;
    else val[u] = 0;
    for(int i=head[u]; i; i=a[i].next)
    {
        int v = a[i].to;
        if(v == fa) continue;
        dfs(v, u, a[i].w);
        val[u] += val[v];
    }
    if(!vis[u] && val[u]) val[u] += w;
    //printf("val[%d] = %d\n", u, val[u]);
}

void calc(int num)
{
    //printf("New Case %d\n", num);
    for(int i=l; i<=r; i++) vis[i] = 0;
    ext.clear();
    for(int i=1; i<=r-l+1; i++)
    {
        if(num&(1<<i-1)) vis[l+i-1] = 1, ext.push_back(l+i-1);
    }
    //for(int i=1; i<=n; i++) printf("%d ", vis[i]);
    //printf("\n");
    int lca = LCA(ext[0], ext[1]);
    for(int i=2; i<ext.size(); i++)
    {
        lca = LCA(lca, ext[i]);
    }
    dfs(lca, fa[lca], 0);
    ans = max(ans, val[lca]);
}

ll dfs2(int u, int fa)
{
    ll sum1 = 0, sum2 = 0;
    for(int i=head[u]; i; i=a[i].next)
    {
        int v = a[i].to;
        if(v == fa) continue;
        if((l <= v && v <= r) || vis[v]) 
        {
            sum2 = max(sum2, dfs2(v, u)+a[i].w);
            vis[u] = 1;
            if(sum2 > sum1) swap(sum2, sum1);
        }
    }
    printf("sum1 = %lld sum2 = %lld\n", sum1, sum2);
    ans = max(ans, sum1 + sum2);
    return sum1;
}

void dfs2(int u, int fa, ll depth)
{
    if(l <= u && u <= r) ans = max(ans, depth);
    for(int i=head[u]; i; i=a[i].next)
    {
        int v = a[i].to;
        if(v == fa) continue;
        dfs2(v, u, depth+a[i].w);
    }
}

void solve2()
{
    //dfs2(1, 0);
    //printf("%lld\n", ans);
    for(int i=l; i<=r; i++)
    {
        dfs2(i, 0, 0);
    }
    printf("%lld\n", ans);
}

int main()
{
    //freopen("1.in", "r", stdin);
    freopen("number.in", "r", stdin);
    freopen("number.out", "w", stdout);

    n = read();
    for(int i=1; i<n; i++)
    {
        int x = read(), y = read(), w = read();
        add(x, y, w); add(y, x, w);
    }
    find_heavy_edge(1, 1, 1); 
    connect_heavy_edge(1, 1);
    q = read();
    while(q--)
    {
        l = read(), r = read(), k = read();
        if(k == 1)
        {
            printf("0\n"); continue;
        }
        if(k == 2)
        {
            ans = 0; solve2(); continue;
        }
        for(int i=1; i<=n; i++) vis[i] = 0;
        Max = 1 << (r-l+1); ans = 0;
        for(int i=0; i<Max; i++)
        {
            if(count(i) != k) continue;
            calc(i);
        }
        printf("%lld\n", ans);
    }

    return 0;
}

 

D. 小j 的组合

注意事项是操作编号和结果序列要求一一对应,不能根据度数预处理。。就这我赛时没切了它就很离谱

code
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 103;

int n, ans, d[maxn], cnt, nct[maxn];
vector<int> v1, v2, v3;
bool vis[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int next, to;
}a[maxn<<1];
int head[maxn], len;

void add(int x, int y)
{
    a[++len].to = y; a[len].next = head[x];
    head[x] = len;
}

void update(int depth)
{
    ans = depth;
    v1.clear();
    for(int i=1; i<=depth; i++)
    {
        v1.push_back(d[i]);
    }
}

void dfs(int u, int fa, int depth)
{
    d[depth] = u;
    int son = 0;
    for(int i=head[u]; i; i=a[i].next)
    {
        int v = a[i].to;
        if(v == fa) continue;
        dfs(v, u, depth+1);
        son++;
    }
    if(son == 0 && depth > ans) update(depth);
}

void dfs2(int u, int fa)
{
    v3.push_back(u);
    for(int i=head[u]; i; i=a[i].next)
    {
        int v = a[i].to;
        if(v == fa || v == nct[u]) continue;
        dfs2(v, u);
        v3.push_back(++cnt);
        v2.push_back(u);
    }
    if(nct[u])
    {
        dfs2(nct[u], u);
    }
}

int main()
{
    freopen("combo.in", "r", stdin);
    freopen("combo.out", "w", stdout);
    
    n = read();
    for(int i=1; i<n; i++)
    {
        int x = read(), y = read();
        add(x, y); add(y, x);
    }
    for(int i=1; i<=n; i++)
    {
        dfs(i, i, 1);
    }
    int sz = v1.size(); cnt = n;
    for(int x : v1) vis[x] = 1;
    for(int i=0; i<sz-1; i++)
    {
        nct[v1[i]] = v1[i+1];
    }
    dfs2(v1[0], 0);
    int sz2 = v2.size();
    printf("%d\n", sz2);
    for(int i=0; i<sz2; i++)
    {
        printf("%d ", v2[i]);
    }
    printf("\n");
    for(int x : v3)
    {
        printf("%d ", x);
    }

    return 0;
}
posted @ 2022-10-19 17:03  Catherine_leah  阅读(10)  评论(1编辑  收藏  举报
/* */