zoukankan      html  css  js  c++  java
  • 五一省选集训Day1

    A

    先搞个多项式 (P(x)) ,次数为 (i) 的系数表示随机一次给 (z) 加上 (i) 的概率(也就是输入)。如果你求出来 (Q=P^n),答案显然是 (sum_{i=0}^{x-1}iQ[i]+x(1-sum_{i=0}^{x-1}Q[i]))

    40pts

    考场上写的做法 (O(xlog xlog n))

    只需要写个 NTT 直接倍增求多项式快速幂就好了

    60pts

    [egin{aligned} Q=P^n \ ln Q = nln P\Q=e^{n ln P} end{aligned} ]

    板子拉一拉就好了。(O(xlog x))

    注意做多项式 exp 的前提是要没有常数项 也就是这个多项式的常数项要求是 1。这个题目保证了有常数项 如果没有的话我们就可以通过除掉一个单项式来让最低位是常数项 最后加回去即可,

    100pts

    好像是个新科技(或套路)

    我们考虑 (P^{n+1}) 的两种求导方法,并加以推导:

    [egin{aligned} (P^{n+1})' = (n+1)P^{n}P'\(P^{n+1})' = (P*P^n)' = P(P^{n})'+P'P^n\(n+1)P^nP'=P(P^{n})'+P'P^n \ nP^nP'=P(P^{n})'\nQP'=PQ' end{aligned} ]

    考虑我们拿出多项式的第 (n)

    [egin{aligned} nsum_{i=1}^k iP[i]Q[n-i+1] = sum_{i=0}^k (n-i+1)P[i]Q[n-i+1]\Q[n+1]=frac{nsum_{i=1}^k iP[i]Q[n-i+1]-sum_{i=1}^k (n-i+1)P[i]Q[n-i+1]}{(n+1)P[0]} end{aligned} ]

    代入计算即可。时间复杂度 (O(xk))

    #include<bits/stdc++.h>
    
    #define fi first
    #define se second
    #define U unsigned
    #define LL long long
    #define pb push_back
    #define MP std::make_pair
    #define all(x) x.begin(),x.end()
    #define CLR(i,a) memset(i,a,sizeof(i))
    #define FOR(i,a,b) for(int i = a;i <= b;++i)
    #define ROF(i,a,b) for(int i = a;i >= b;--i)
    #define DEBUG(x) std::cerr << #x << '=' << x << std::endl
    
    const int MAXN = 1e7 + 5;
    const int ha = 998244353;
    int n,k,x;
    int P[MAXN],Q[MAXN];
    
    inline int qpow(int a,int n=ha-2){
    	int res = 1;
    	while(n){
    		if(n & 1) res = 1ll*res*a%ha;
    		a = 1ll*a*a%ha;
    		n >>= 1;
    	}
    	return res;
    }
    
    int main(){
    	scanf("%d%d%d",&n,&k,&x);
    	int sm = 0;
    	FOR(i,0,k) scanf("%d",P+i),sm += P[i];
    	sm = qpow(sm);
    	FOR(i,0,k) P[i] = 1ll*P[i]*sm%ha;
    	Q[0] = qpow(P[0],n);int inv=qpow(P[0]);
    	int ans = 0;sm = Q[0];
    	FOR(i,1,x-1){
    		FOR(j,1,std::min(i,k)){
    			(Q[i] += 1ll*j*P[j]%ha*Q[i-j]%ha) %= ha;
    		}
    		Q[i] = 1ll*Q[i]*n%ha;
    		FOR(j,1,std::min(i,k)) (Q[i] += ha-1ll*(i-j)*P[j]%ha*Q[i-j]%ha) %= ha;
    		Q[i] = 1ll*Q[i]*inv%ha*qpow(i)%ha;
    		(ans += 1ll*i*Q[i]%ha) %= ha;
    		(sm += Q[i]) %= ha;
    	}
    	(ans += 1ll*x*(ha+1-sm)%ha) %= ha;
    	printf("%d
    ",ans);
    	return 0;
    }
    

    B

    60pts做法

    考场做法

    我们先考虑最后一段连续的都是1的情况

    设最后一个 (0) 的位置是(p) ,这个字符串被随机出的概率显然是 (2^{-p})

    于是我们去枚举这个 (p),考虑计算出方案数 乘一下概率就好。

    枚举这些钦定的位置是全 0 还是全 1 ,分类讨论一下:

    全 0:显然 (p) 后面不能存在钦定的位置 然后组合数选一下 再按照 (p) 位置是否被钦定组合数一下(如果没被钦定 这个位置不能被涂1 要减去)

    全 1:首先 (p) 这个位置不能被钦定,然后记录一下 (p) 前面有多少个钦定了的位置 剩下的位置组合数算一下选出0 的位置即可。

    另一种情况翻转过来就可以 所以答案要乘 (2)

    #include<bits/stdc++.h>
    
    #define fi first
    #define se second
    #define U unsigned
    #define P std::pair<int,int>
    #define LL long long
    #define pb push_back
    #define MP std::make_pair
    #define all(x) x.begin(),x.end()
    #define CLR(i,a) memset(i,a,sizeof(i))
    #define FOR(i,a,b) for(int i = a;i <= b;++i)
    #define ROF(i,a,b) for(int i = a;i >= b;--i)
    #define DEBUG(x) std::cerr << #x << '=' << x << std::endl
    
    inline char nc(){
        #define SIZE 1000000+3
        static char buf[SIZE],*p1 = buf+SIZE,*p2 = buf+SIZE;
        if(p1 == p2){
            p1 = buf;p2 = buf+fread(buf,1,SIZE,stdin);
            if(p1 == p2) return -1;
        }
        return *p1++;
        #undef SIZE
    }
    
    template <typename T>
    inline void read(T &x){
        x = 0;int flag = 0;char ch = nc();
        while(!isdigit(ch)){
            if(ch == '-') flag = 1;
            ch = nc();
        }
        while(isdigit(ch)){
            x = (x<<1) + (x<<3) + (ch^'0');
            ch = nc();
        }
        if(flag) x = -x;
    }
    
    const int MAXN = 2e5 + 5;
    const int ha = 998244353; 
    int a[MAXN];
    int n,q;
    
    int fac[MAXN],inv[MAXN];
    
    inline int qpow(int a,int n=ha-2){
    	int res = 1;
    	while(n){
    		if(n & 1) res = 1ll*res*a%ha;
    		a = 1ll*a*a%ha;
    		n >>= 1;
    	}
    	return res;
    }
    
    inline void prework(){
    	fac[0] = 1;
    	FOR(i,1,MAXN-1) fac[i] = 1ll*fac[i-1]*i%ha;
    	inv[MAXN-1] = qpow(fac[MAXN-1]);
    	ROF(i,MAXN-2,0) inv[i] = 1ll*inv[i+1]*(i+1)%ha;
    }
    
    inline int C(int n,int m){
    	if(n < m) return 0;
    	if(!m) return 1;
    	return 1ll*fac[n]*inv[m]%ha*inv[n-m]%ha;
    }
    int sm[MAXN];
    const int inv2=(ha+1)/2;
    int pw[MAXN];
    int main(){
    	prework();
    	read(n);read(q);int all = 0;
    	pw[0] = 1;FOR(i,1,MAXN-1) pw[i] = 1ll*pw[i-1]*inv2%ha;
    	while(q--){
    		int k;read(k);int mx = 0;
    		FOR(i,1,k) read(a[i]),mx = std::max(mx,a[i]);
    		FOR(i,1,2*n) sm[i] = 0;FOR(i,1,k) sm[a[i]] = 1;
    		FOR(i,1,2*n) sm[i] += sm[i-1];
    		int ans = 0;
    		FOR(i,n,2*n-1){//最后一个 0
    			int t0=n,t1=i-n;
    			if(mx <= i){
    				(ans += 1ll*pw[i]*C(i-k-(sm[i]-sm[i-1]==0),t1)%ha)%=ha;
    			}
    			if(sm[i]-sm[i-1] == 0) (ans += 1ll*pw[i]*C(i-1-sm[i],n-1)%ha) %= ha;
    		}
    		ans = 1ll*ans*2%ha;
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    100pts做法

    大家肯定都会去想搞个前缀和快速维护 但是我考场上以为要对于每个 (k) 维护就自闭了。

    我们注意到 本质不同的 (k) 的种类数只会有 (O(sqrt {sum k})) 个。

    证明考虑等差数列求和即可。

    于是我们现在枚举 (k) 把询问放在一起处理,下面我们来对着上面的代码优化:

    if(mx <= i){
    	(ans += 1ll*pw[i]*C(i-k-(sm[i]-sm[i-1]==0),t1)%ha)%=ha;
    }
    

    如果这一位没有被钦定就是 (pw[i]inom {i-k-1}{i-n}) 否则是 (pw[i]inom {i-k}{i-n})

    我们去枚举计算被钦定的位 没背钦定的一定被分成若干段 预处理 (pw[i]inom{i-k-1}{i-n}) 的前缀和即可。注意一下边界 x1

    if(sm[i]-sm[i-1] == 0) (ans += 1ll*pw[i]*C(i-1-sm[i],n-1)%ha) %= ha;
    

    这个有点难。。我想了一会。

    我们还是去找出中间那些段,然后我们发现每段内一定是形如 (pw[i]*inom{i-1-c}{n-1}) 的形式 (c) 是和前面有多少个被钦定的位置的数量。那么我们预处理出来 (pw[i]*inom {i-1}{n-1}) 的前缀和,发现一段一定会整体少乘 (pw[c]) 乘上去就好了。注意边界 x2

    发现上面的所有操作都是和 (k) 有关的 所以复杂度是很正确的 (O(nsqrt n))(n,k,q)同阶)

    C

    好像你需要猜结论:在如此小的数据范围内 每个组最多只会有两个集合。

    如果是奇数的 subtask 的话直接把大小为 (i) 和大小为 (k-i) 的连边 搞个二分图屁屁额就好了。

    于是跑一个一般图最大匹配 但是我不会带花树 所以咕咕咕了。反正也不太会。。

  • 相关阅读:
    Java+7入门经典 -1 简介
    优化算法动画演示Alec Radford's animations for optimization algorithms
    如何写科技论文How to write a technical paper
    开始学习深度学习和循环神经网络Some starting points for deep learning and RNNs
    用500行Julia代码开始深度学习之旅 Beginning deep learning with 500 lines of Julia
    用10张图来看机器学习Machine learning in 10 pictures
    ICLR 2013 International Conference on Learning Representations深度学习论文papers
    ICLR 2014 International Conference on Learning Representations深度学习论文papers
    卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现
    卷积神经网络Convolutional Neural Networks
  • 原文地址:https://www.cnblogs.com/rainair/p/14471616.html
Copyright © 2011-2022 走看看