其他分享
首页 > 其他分享> > 牛客第四场

牛客第四场

作者:互联网

新学期开始了,Bob 需要开始选课了。

 

 

 

 学校有n门课程,第i门课的学分是si 。  Bob在同一门课程中可以选择多次,如果他为第i门课程选择ki 次,他的总学分是∑i=1到n ki*si

 

 

 

 而且 Bob 的培训计划有一些局限性。  训练计划是这些n课程的有根树,每个限制意味着x子树中的总学分需要至少为cx 。

 

 

 

 现在Bob想知道满足培训计划限制的选课方式的数量,总学分是w。

 

 

 

 两种方式不同当且仅当存在至少一个 i∈[1,n]满足第 i 个课程的选择次数在这两个计划。

 

 

 

 答案可能很大,你只需要输出答案模块998244353即可。

输入描述:
第一行有两个整数 n,Q。 那么有n-1行来描述训练程序的有根树,每行有两个整数a,b表示a是b的父节点。 下一行有 n个整数 s1...n 。 下一行有 n 个整数 c1...n 。 然后是Q行,每一行有一个整数wi 表示第i个查询的总积分。

输出描述:

输出Q行,每一行有一个整数表示第i个查询的答案。

#include<bits/stdc++.h>
using namespace std;
const int N=105, mo=998244353, P=mo;
#define pb push_back
#define rep(i,j,k) for(int i=(int)(j);i<=(int)(k);i++)
#define per(i,j,k) for(int i=(int)(j);i>=(int)(k);i--)
#define se second
#define fi first
typedef long long ll;
ll pw(ll x,int p){
    ll ans=1;do{if(p&1)ans = ans*x%mo; x = x*x%mo;
    }while(p>>=1);
    return ans;
}
 
vector<int>to[N];
int n,Q, sc[N], lw[N];
 
struct ply{
    vector<int> f;
    ply(int l=0){
        f.resize(l);
        for(int i=0;i<l;++i)f[i]=0;
    }
    ply(int l, ply &g){
        f.resize(l);
        for(int i=0,j=min(l,g.sz());i<j;++i)f[i]=g[i];
        for(int i=g.sz();i<l;++i)f[i]=0;
    }
    ply(const ply &g){
        f.resize(g.sz());
        for(int i=0,j=g.sz();i<j;++i)f[i]=g.f[i];
    }
    int sz() const {return f.size();}
    void pb(int x){f.push_back(x);}
     
    int& operator[](int x){return f[x];}
     
    ply operator^(ply g){
        int sum = 0; for(auto x:g.f)sum += x;
        ply b(sz() + sum, *this);
        for(auto x:g.f){
            for(int i=b.sz()-1;i;--i){
                if(i>=x)b[i] = (b[i] + mo - b[i-x]) % mo;
            }
        }
        return b;
    }
     
    ply operator-(ply b){
        ply c(max(sz(), b.sz()), *this);
        for(int i=0,j=b.sz();i<j;++i)c[i] = (c[i] + mo - b[i]) % mo;
        return c;
    }
     
    ply operator*(ply b){
        ply c(sz() + b.sz() - 1);
        for(int i=0, ik=sz(); i<ik; ++i)
            for(int j=0, jk=b.sz(); j<jk; ++j)
                c[i+j] = (c[i+j] + 1ll * f[i] * b[j]) % mo;
        return c;
    }
};
 
pair<ply, ply> operator/(ply a, ply b){
    if(a.sz() < b.sz()){
        return make_pair(ply(1), ply(b.sz(), a));
    }
    ply c(a.sz()-b.sz() + 1);
    for(int i=a.sz()-1, j=b.sz()-1;i>=j;--i){
        int w = 1ll * a[i] * pw(b[j], mo-2) % mo;
        c[i-j] = w;
        for(int k=0; k<=j; ++k)a[i-k] = (a[i-k] + mo - 1ll * w * b[j-k] % mo) % mo;
    }
    ply r(b.sz(), a);
    return make_pair(c,r);
}
 
ply mpw(ply x, int p, ply md){
    ply r;r.pb(1);
    do{
        if(p&1)r = ((x * r) / md).second;
        x = ((x * x) / md).second;
    }while(p>>=1);
    return r;
}
 
int calc(ply f, ply g, int n){
    if(g.sz() - 1 == 0)return (n <= f.sz() -1)? f[n] : 0;
    ///////////////////////
    assert(f.sz()==g.sz());
    assert(f[g.sz()-1]==0);
    f.f.pop_back();
    ply t(2);t[1]=1;
    ply r = mpw(t,n,g);
    int ans = 0;
    for(int i = 1; i < r.sz(); ++i){
        for(int j = 1; j <= i; ++j)f[i] = (f[i] + 1ll * f[i-j] * (mo - g[j])) % mo;
    }
    for(int i = 0; i < r.sz(); ++i){
        ans = (ans + 1ll * r[i] * f[i]) % mo;
    }
    return ans;
}
 
struct Poly{
    ply f,g;
    void unit(){
        f.pb(1);
    }
    int get(int x){
        ply d;d.pb(1);
        d = d ^ g;
 
        auto e=f/d;
        int ans=0;if(e.fi.sz()>=x+1)ans=e.fi[x];
 
        ans=(ans+calc(e.se,d,x))%P;
 
        return ans;
    }
     
    void mrg(Poly b){
        for(int x:b.g.f)g.pb(x);
        f = f * b.f;
    }
     
    void drp(int k){
        ply d(k, f);
        for(auto x:g.f){
            for(int i=x;i<k;++i)d[i] = (d[i-x] + d[i]) % mo;
        }
        f = f - (d^g);
    }
} dp[N];
 
void dfs(int x){
    dp[x].unit();
    dp[x].g.pb(sc[x]);
    for(int y:to[x]){
        dfs(y);
        dp[x].mrg(dp[y]);
    }
    dp[x].drp(lw[x]);
}
 
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>Q;
    for(int i=1,a,b;i<n;++i){
        cin>>a>>b;
        to[a].pb(b);
    }
    for(int i=1;i<=n;++i)cin>>sc[i];
    for(int i=1;i<=n;++i)cin>>lw[i];
    dfs(1);
    while(Q--){
        int v;cin>>v;
        cout<<dp[1].get(v)<<'\n';
    }
    return 0;
}

 

 

B

Bob 有一个随机数生成器,它会以 px的概率生成 x。

现在 Bob 将执行以下操作:

步骤 1. 通过随机数生成器生成一个数字 x。

步骤 2 如果 x 是生成数中最大的数(即 x 不小于任何先前生成的数),则转至步骤 1,否则转至步骤 3。

步骤 3. 如果 Bob 总共生成 x 个数字,Bob 将得到 x^2的分数。

现在鲍勃想知道他将得到的分数的期望值。

如果答案是不可约分数 x/y ,则需要在 [0,998244352] 中输出一个整数 d,满足 d×y mod 998244353=x mod 998244353。保证y mod 998244353≠0。

输入:

第一行有一个整数n,表示随机数生成器只能生成[1,n]中的整数。

第二行有 n个正整数 w1...n ,表示 pi=wi/∑j=1到n wj 。 2≤n≤100。 1≤wi≤10^6

输出:

输出答案

#include<stdio.h>
#include<stdlib.h>
void exgcd(long long a,long long &x0,long long b,long long &y0,long long &d)
{
    if(b==0)
    {
        x0=1,y0=0,d=a;
        return;
    }
    long long x1,y1;
    exgcd(b,x1,a%b,y1,d);
    x0=y1;
    y0=x1-(a/b)*y1;
}
long long inv(long long a,long long mod)
{
    long long x,y,d;
    exgcd(a,x,mod,y,d);
    if(d!=1)
        return -1;
    return (x%mod+mod)%mod;
}
int main()
{
    long long f1=1,f2=0,p[100],sum=0,w[100];
    int i,n;
    const long long mod=998244353;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%lld",&w[i]);
        sum+=w[i];
    }
    int invsum=inv(sum,mod);
    for(i=0;i<n;i++)
    {
        f1=(f1*sum%mod)*inv(sum-w[i],mod)%mod;
        f2=(w[i]*inv(sum-w[i],mod)%mod+f2)%mod;
    }
    int res=(2*f1*f2%mod+f1)%mod;
    printf("%lld",res);
}

 

 

C

 

#include <iostream>
#include <algorithm>
 
using namespace std;
 
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int a, b, c, n;
    cin >> a >> b >> c >> n;
 
    int l1 = min(a, min(b, c)), l2, l3;
 
    if (l1 == a) l2 = min(b, c), l3 = max(b, c);
    if (l1 == b) l2 = min(a, c), l3 = max(a, c);
    if (l1 == c) l2 = min(a, b), l3 = max(a, b);
    // l1 < l2 < l3
 
    int ok = l1 + (l2 - l1) + (l3 - l1);
 
    if (ok > n)
    {
        cout << "NO" << endl;
        return 0;
    }
 
    string s1 = string(l1, 'a'), s2 = s1, s3 = s1;
 
    l2 -= l1, l3 -= l1, a -= l1, b -= l1, c -= l1;
 
    if (l2 == a) s1 += string(l2, 'b'), s2 += string(l2, 'b'), s3 += string(l2, 'c');
    if (l2 == b) s2 += string(l2, 'b'), s3 += string(l2, 'b'), s1 += string(l2, 'c');
    if (l2 == c) s1 += string(l2, 'b'), s3 += string(l2, 'b'), s2 += string(l2, 'c');
 
    if (l3 == a) s1 += string(l3, 'd'), s2 += string(l3, 'd'), s3 += string(l3, 'e');
    if (l3 == b) s2 += string(l3, 'd'), s3 += string(l3, 'd'), s1 += string(l3, 'e');
    if (l3 == c) s1 += string(l3, 'd'), s3 += string(l3, 'd'), s2 += string(l3, 'e');
 
    int len = n - l1 - l2 - l3;
    s1 += string(len, 'x'), s2 += string(len, 'y'), s3 += string(len, 'z');
 
    cout << s1 << endl << s2 << endl << s3 << endl;
 
    return 0;
}

 

 

D

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL long long
#define eps 1e-8
#define N 50010
#define M 100010
#define MOD 998244353
 
using namespace std;
 
int n, K;
int idc = 0;
int head[N];
int siz[N];
LL dp[N][105][2];
LL tmp[105][2];
 
struct Edge{
    int to;
    int nxt;
}ed[N * 2];
 
LL quickmuit(LL a, LL b) {
    LL ans = 1;
    for( ; b; b >>= 1, (a *= a) %= MOD)
        if (b & 1)
            (ans *= a) %= MOD;
    return ans;
}
 
void adde(int u, int v) {
    ed[++idc].to = v;
    ed[idc].nxt = head[u];
    head[u] = idc;
}
 
void DP(int u, int fa) {
    siz[u] = 1;
    dp[u][0][0] = 1; dp[u][0][1] = 1;
    for(int k = head[u]; k; k = ed[k].nxt) {
        int v = ed[k].to;
        if (v == fa) continue;
        DP(v, u);
        memset(tmp, 0, sizeof(tmp));
        for(int i = 0; i < siz[u] && i <= K; i ++) {
            for(int j = 0; j < siz[v] && i + j <= K; j ++) {
                tmp[i + j][0] += dp[u][i][0] * dp[v][j][0] % MOD;
                tmp[i + j][0] %= MOD;
                tmp[i + j][1] += (dp[u][i][1] * dp[v][j][0] + dp[u][i][0] * dp[v][j][1]) % MOD;
                tmp[i + j][1] %= MOD;
                if (i + j == K) continue;
                tmp[i + j + 1][0] += dp[u][i][0] * dp[v][j][1] % MOD;
                tmp[i + j + 1][0] %= MOD;
                tmp[i + j + 1][1] += dp[u][i][1] * dp[v][j][1] % MOD;
                tmp[i + j + 1][1] %= MOD;
            }
        }
        memcpy(dp[u], tmp, sizeof(tmp));
        siz[u] += siz[v];
    }
}
 
int main() {
    cin >> n >> K;
    for (int i = 1; i < n; i ++) {
        int u, v; cin >> u >> v;
        adde(u, v); adde(v, u);
    }
    DP(1, 0);
    LL ans = dp[1][K][1] * quickmuit(n, K - 1) % MOD;
    cout << ans << endl;
    return 0;
}

 

 E

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define pii pair<int,int>
const int N = 1e6;
vector<pii>v[N];
vector< pii > ans;
int w[N], L[N], R[N];
bool vis[N];
void dfs(int now, int pre, int ww)
{
    for(auto it : v[now])
    {
        if(it.first == pre) continue;
        w[it.first] = ww ^ it.second;
        dfs(it.first, now, w[it.first]);
    }
}
 
void insert(int L, int R, int l, int r, int w)
{
     
    if(l <= L && r >= R)
    {
        int LL = L ^ (w & (~(R - L)) ) ;
        int RR = LL + (R-L);
//        cout<<l << " " << r << " "<< LL  << " " << RR << endl;
        ans.push_back(make_pair(LL, 1));
        ans.push_back(make_pair(RR+1, -1));
        return;
    }
    int mid = L + R >> 1;
    if(l <= mid) insert(L, mid, l, r, w);
    if(r > mid)  insert(mid+1, R, l, r, w);
}
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> L[i] >> R[i];
    }
    for(int i = 1; i < n; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        v[a].push_back(make_pair(b, c)), v[b].push_back(make_pair(a, c));
    }
    dfs(1,0,0);
    for(int i = 1; i <= n; i++)
    {
        insert(0, (1<<30)-1, L[i], R[i], w[i]);
    }
    sort(ans.begin(), ans.end());
    int res = 0, all = 0;
    for(int i = 0; i < ans.size() - 1; i++)
    {
        all += ans[i].second;
        if(all == n)
        res += ans[i+1].first - ans[i].first;
    }
    cout << res;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:sz,第四场,int,ply,牛客,long,ans,include
来源: https://www.cnblogs.com/EVANGELION-01/p/15082875.html