2022NOIPA层联测32

有人知道 for(int x : vec) ...这东西noip考场上能不能用啊?今天上午想用来着结果过不了编译??

 

B. 鸟之诗 (air)

赛时只会全排列y的质因数,并且认为用a和b把x和y乘起来麻烦死了……丝毫都没有往正解那方面想……

5 pts

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 3;
const int mod = 998244353;

int p[10], n, m, fz[10], num, b[10];
ll x, y, ans;

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;
}

inline int gcd(int a, int b)
{
    while(b^=a^=b^=a%=b);
    return a;
}

inline int lcm(int x, int y)
{
    int d = gcd(x, y);
    return x / d * y;
}

void calc()
{
    int d = b[1];
    for(int i=2; i<=n; i++)
    {
        d = gcd(d, b[i]);
    }
    if(d != x) return;
    d = b[1];
    for(int i=2; i<=n; i++)
    {
        d = lcm(d, b[i]);
    }
    if(d != y) return;
    ans++;
}

void dfs(int a)
{
    if(a > n)
    {
        calc(); return;
    }
    for(int i=1; i<=num; i++)
    {
        if(fz[i] < x) continue;
        b[a] = fz[i];
        dfs(a+1);
    }
}

int main()
{
	freopen("air.in", "r", stdin);
    freopen("air.out", "w", stdout);
    
    m = read(); n = read();
    p[1] = 2, p[2] = 3, p[3] = 5, p[4] = 7, p[5] = 11, p[6] = 13;
    x = 1, y = 1;
    for(int i=1; i<=m; i++) 
    {
        int l = read();
        int res = 1;
        for(int j=1; j<=l; j++) res *= p[i];
        x = x * res; 
    }
    for(int i=1; i<=m; i++)
    {
        int l = read(); 
        int res = 1;
        for(int j=1; j<=l; j++) res *= p[i];
        y = y * res;
    }
    for(int i=1; i<=sqrt(y); i++)
    {
        if(y % i == 0) 
        {
            fz[++num] = i;
            if(i * i != y) fz[++num] = y / i;
        }
    }
    dfs(1);
    ans %= mod;
    printf("%lld\n", ans);
	
	return 0;
}
code
 #include <bits/stdc++.h>

using namespace std;

//#define int long long
typedef long long ll;
const int maxn = 1e6 + 7;
const int mod = 998244353;

ll m, n, a[maxn], b[maxn];
ll ans = 1;

inline ll read()
{
    ll 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;
}

int main()
{
    freopen("air.in", "r", stdin);
    freopen("air.out", "w", stdout);
    
    m = read(); n = read(); n %= (mod-1);
    for(int i=1; i<=m; i++) a[i] = read();
    for(int i=1; i<=m; i++) b[i] = read();
    for(int i=1; i<=m; i++)
    {
        if(a[i] == b[i]) continue;
        ll res = (qpow(b[i]-a[i]+1, n)-2ll*qpow(b[i]-a[i], n)%mod+qpow(b[i]-a[i]-1, n))%mod;
        res = (res + mod) % mod;
        ans = ans * res % mod;
    }
    printf("%lld\n", ans);

    return 0;
}

 

D. 无双挑战 (challenge)

把树上距离拆开,不好算的就只有dep[lca]求和,解决方法是从upd这个点到根区间加1,query统计点到根区间求和(把加的1合起来就是深度嘛),严格大于就把相等的拆出来一起算。

这题本来没有坑,So我给自己挖了坑跳了进去:区间修改的线段树不打lazy,在范围内的时候t[x].sum+=v没乘区间长度,把 j 写成 i ,(l+r)>>1写成(l+1)>>1,结果就是就这题还调了一下午!?并且因为long long没开全先炸没了菊花图的部分分,正解又挂了一次96……

我这才多久没写线段树区间求和……

把上次联测的sily错误也在这里说一下好了(那天博客园登不上去):那个最短路的题就算不开根号也都知道是三分,我写了个二分就&*@#¥,我不知道为什么当我看到x + d/(x+1)这个函数时居然以为它单调递增??用脚想都说不通,它单点递增我还分个什么鬼!?

我这才多久没做数学T……

顺便说一下今天的T3他给的式子直接用就30结果我从1循环到了m似乎根本就不知道区间划分是从二维开始的,过不了样例以为是他的提示不能推广……

32 pts
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 4;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;

int n, m, dep[maxn], top[maxn], siz[maxn], fa[maxn], son[maxn];
int v[maxn];
ll ans;

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 nxt, to;
}e[maxn<<1];
int head[maxn], len;

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

void find_heavy_edge(int u, int fat, int depth)
{
    fa[u] = fat;
    dep[u] = depth;
    siz[u] = 1;
    son[u] = 0;
    int maxsize = 0;
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        if(v == fat) 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=e[i].nxt)
    {
        int v = e[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;
}

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;
}

ll sum[maxn];
struct node2 
{
    int id, v;
    bool operator < (const node2 &T) const 
    {
        return v < T.v;
    }
}p[maxn];

int find(int mv)
{
    int l = 1, r = n + 1;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        if(p[mid].v > mv) r = mid;
        else l = mid + 1;
    }
    return l;
}

void solveflwr()
{
    ll res = 0;
    for(int i=2; i<=n; i++)
    {
        if(v[i] > v[1]) ans++;
        else if(v[1] > v[i]) res = (res + m - v[i]) % mod;
    }
    ans = ans * (m - v[1]) % mod;
    for(int i=1; i<n; i++) p[i].v = v[i+1];
    sort(p+1, p+n); p[n].v = inf;
    for(int i=1; i<n; i++)
    {
        int pos = find(p[i].v);
        ans = (ans+1ll*(m-p[i].v)*(n-pos+n-pos)%mod)%mod;
    }
    ans = (ans + res) % mod;
    ll t = qpow(1ll*n*(n-1)%mod, mod-2);
    ans = ans * t % mod;
    printf("%lld\n", ans);
    exit(0);
}

int main()
{
	freopen("challenge.in", "r", stdin);
    freopen("challenge.ans", "w", stdout);
    
    n = read(); m = read(); bool fl = 1;
    for(int i=1; i<=n; i++) v[i] = read();
    for(int i=1; i<n; i++)
    {
        int u = read(), v = read();
        if(u > v) swap(u, v);
        if(u != 1) fl = 0;
        add(u, v); add(v, u);
    }
    if(fl) solveflwr();
    find_heavy_edge(1, 0, 1);
    connect_heavy_edge(1, 1);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(v[j] <= v[i]) continue;
            int lca = LCA(i, j);
            int dis = dep[i] - dep[lca] + dep[j] - dep[lca];
            ans = (ans + (ll)(m - v[i]) * dis % mod) % mod;
        }
    }
    ll t = qpow(1ll*n*(n-1)%mod, mod-2);
    ans = ans * t % mod;
    printf("%lld\n", ans);
	
	return 0;
}
code
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
//#define int ll
const int maxn = 8e5 + 4;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;

int n, m, sumdep, ans, flly;
int dep[maxn], siz[maxn], son[maxn], fa[maxn], top[maxn], dfn[maxn], dfn_c;

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 a, id;
    bool operator < (const node &T) const 
    {
        return a > T.a;
    }
}p[maxn];

struct node2 
{
    int nxt, to;
}e[maxn<<1];
int head[maxn], len;

void add_e(int x, int y)
{
    e[++len].to = y; e[len].nxt = head[x];
    head[x] = len;
}

inline void add(int &x, int y) {x=(x+y)%mod;}

struct seg 
{
    struct tree 
    {
        int sum, lazy;
    }t[maxn<<2];
    void pushup(int x)
    {
        t[x].sum = (t[x<<1].sum + t[x<<1|1].sum) % mod;
    }
    void pushdown(int x, int l, int r)
    {
        int ls = x<<1, rs = x<<1|1, mid = (l + r) >> 1;
        add(t[ls].lazy, t[x].lazy);
        add(t[rs].lazy, t[x].lazy);
        add(t[ls].sum, 1ll*(mid-l+1)*t[x].lazy%mod);
        add(t[rs].sum, 1ll*(r-mid)*t[x].lazy%mod);
        t[x].lazy = 0;
    }
    void update(int x, int l, int r, int L, int R, int v)
    {
        if(L <= l && r <= R)
        {
            add(t[x].sum, 1ll*v*(r-l+1)%mod); add(t[x].lazy, v);
            return;
        }
        if(t[x].lazy) pushdown(x, l, r);
        int mid = (l + r) >> 1;
        if(L <= mid) update(x<<1, l, mid, L, R, v);
        if(R > mid) update(x<<1|1, mid+1, r, L, R, v);
        pushup(x);
    }
    int query(int x, int l, int r, int L, int R)
    {
        if(L <= l && r <= R) return t[x].sum;
        if(t[x].lazy) pushdown(x, l, r);
        int mid = (l + r) >> 1, ans = 0;
        if(L <= mid) add(ans, query(x<<1, l, mid, L, R));
        if(R > mid) add(ans, query(x<<1|1, mid+1, r, L, R));
        return ans;
    }
}t;

void find_heavy_edge(int u, int fat, int depth)
{
    fa[u] = fat;
    dep[u] = depth;
    siz[u] = 1;
    son[u] = 0;
    int maxsize = 0;
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        if(v == fat) 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;
    dfn[u] = ++dfn_c;
    if(son[u])
    {
        connect_heavy_edge(son[u], ancestor);
    }
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        if(v == fa[u] || v == son[u]) continue;
        connect_heavy_edge(v, v);
    }
}

void upd_ans(int x)
{
    while(top[x] != top[1])
    {
        t.update(1, 1, n, dfn[top[x]], dfn[x], 1);
        x = fa[top[x]];
    }
    t.update(1, 1, n, dfn[1], dfn[x], 1);
}

int get_ans(int x)
{
    int ans = 0;
    while(top[x] != top[1])
    {
        add(ans, t.query(1, 1, n, dfn[top[x]], dfn[x]));
        x = fa[top[x]]; 
    }
    add(ans, t.query(1, 1, n, dfn[1], dfn[x]));
    return ans;
}

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;
}

signed main()
{
	freopen("challenge.in", "r", stdin);
    freopen("challenge.out", "w", stdout);
    
    n = read(), m = read();
    for(int i=1; i<=n; i++)
    {
        p[i].a = read(), p[i].id = i;
    }
    for(int i=1; i<n; i++)
    {
        int u = read(), v = read();
        add_e(u, v); add_e(v, u);
    }
    sort(p+1, p+1+n);
    find_heavy_edge(1, 0, 1);
    connect_heavy_edge(1, 1);
    for(int i=1; i<=n; )
    {
        int l = i, r = i;
        while(r < n && p[r+1].a == p[l].a) r++;
        for(int j=l; j<=r; j++)
        {
            ans = 0;
            add(ans, 1ll*dep[p[j].id]*(l-1)%mod);
            add(ans, sumdep);
            add(ans, (mod-2ll*get_ans(p[j].id)%mod)%mod);
            add(flly, 1ll*ans*(m-p[j].a)%mod);
        }
        for(int j=l; j<=r; j++) add(sumdep, dep[p[j].id]);
        for(int j=l; j<=r; j++) upd_ans(p[j].id);
        i = r + 1;
    }
    flly = 1ll * flly * qpow(1ll*n*(n-1)%mod, mod-2) % mod;
    printf("%d\n", flly);
	
	return 0;
}

 

[LNOI2014]LCA

双倍经验?用到了差分,序列上差分和树上差分形式好像哦,然而我没有想到差分直接写了一个莫队然后T飞了555……还有就是记得多取几个mod,尤其是用到减法的时候(我又出负数了*)

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

using namespace std;

typedef long long ll;
const int maxn = 5e4 + 3;
const int mod = 201314;

int n, m, ans[maxn], sz;
int dep[maxn], fa[maxn], siz[maxn], son[maxn], dfn[maxn], dfn_c, top[maxn];
inline void add(int &x, int y) {x=(x+y)%mod;}

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 que
{
    int id, opt, z;
}q[maxn];
vector<que> v[maxn];

struct seg 
{
    struct tree 
    {
        int sum, lazy;
    }t[maxn<<2];
    void pushup(int x)
    {
        t[x].sum = (t[x<<1].sum + t[x<<1|1].sum) % mod;
    }
    void pushdown(int x, int l, int r)
    {
        int ls = x<<1, rs = x<<1|1, mid = (l + r) >> 1;
        add(t[ls].lazy, t[x].lazy);
        add(t[rs].lazy, t[x].lazy);
        add(t[ls].sum, 1ll*(mid-l+1)*t[x].lazy%mod);
        add(t[rs].sum, (r-mid)*t[x].lazy%mod);
        t[x].lazy = 0;
    }
    void update(int x, int l, int r, int L, int R, int v)
    {
        if(L <= l && r <= R)
        {
            add(t[x].sum, (r-l+1)*v%mod); add(t[x].lazy, v);
            return;
        }
        if(t[x].lazy) pushdown(x, l, r);
        int mid = (l + r) >> 1;
        if(L <= mid) update(x<<1, l, mid, L, R, v);
        if(R > mid) update(x<<1|1, mid+1, r, L, R, v);
        pushup(x);
    }
    int query(int x, int l, int r, int L, int R)
    {
        if(L <= l && r <= R) return t[x].sum;
        if(t[x].lazy) pushdown(x, l, r);
        int mid = (l + r) >> 1, ans = 0;
        if(L <= mid) add(ans, query(x<<1, l, mid, L, R));
        if(R > mid) add(ans, query(x<<1|1, mid+1, r, L, R));
        return ans;
    }
}t;

struct node 
{
    int nxt, to;
}e[maxn];
int head[maxn], len;

void add_e(int x, int y)
{
    e[++len].to = y; e[len].nxt = head[x];
    head[x] = len;
}

void find_heavy_edge(int u, int fat, int depth)
{
    fa[u] = fat;
    dep[u] = depth;
    siz[u] = 1;
    son[u] = 0;
    int maxsize = 0;
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        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;
    dfn[u] = ++dfn_c;
    if(son[u])
    {
        connect_heavy_edge(son[u], ancestor);
    }
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        if(v == son[u] || v == fa[u]) continue;
        connect_heavy_edge(v, v);
    }
}

void upd_ans(int x)
{
    while(top[x] != top[1])
    {
        t.update(1, 1, n, dfn[top[x]], dfn[x], 1);
        x = fa[top[x]];
    }
    t.update(1, 1, n, dfn[1], dfn[x], 1);
}

int get_ans(int x)
{
    int ans = 0;
    while(top[x] != top[1])
    {
        add(ans, t.query(1, 1, n, dfn[top[x]], dfn[x]));
        x = fa[top[x]];
    }
    add(ans, t.query(1, 1, n, dfn[1], dfn[x]));
    return ans;
}

void solve()
{
    for(int i=1; i<=n; i++)
    {
        upd_ans(i);
        for(que x : v[i]) ans[x.id] = (ans[x.id]+1ll*x.opt*get_ans(x.z)%mod+mod)%mod;
    }
}

int main()
{
    n = read(), m = read();
    for(int i=2; i<=n; i++)
    {
        int x = read()+1; add_e(x, i);
    }
    find_heavy_edge(1, 0, 1);
    connect_heavy_edge(1, 1);
    for(int i=1; i<=m; i++)
    {
        int l = read(), r = read(), z = read();
        v[l].push_back((que){i, -1, z+1});
        v[r+1].push_back((que){i, 1, z+1});
    }
    solve();
    for(int i=1; i<=m; i++) printf("%d\n", ans[i]);

    return 0;
}
posted @ 2022-11-21 20:10  Catherine_leah  阅读(50)  评论(13编辑  收藏  举报
/* */