• 正睿2018.9.1提高2


    A 单调栈/凸壳

    题目链接

    题解

    对于二次函数提出一个x
    对于剩下的直线维护一个
    我们需要求出最大值上轮廓
    单调栈求上凸壳就好了

    code

    #include<cstdio> 
    #include<algorithm> 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' || c > '9') { if(c == '-')f = -1;c = getchar();} 
    	while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
    	return x * f; 
    } 
    const int maxn = 500007; 
    int n,q; 
    struct fuc { 
    	int a,b; 
    } a[maxn],q1[maxn],q2[maxn]; 
    bool cmp(fuc a,fuc b) { 
    	return a.a == b.a ? a.b < b.b : a.a < b.a; 
    } 
    double cross(fuc a,fuc b) { 
    	return (double) (b.b - a.b) / (a.a - b.a); 
    } 
    int tp1 = 0,tp2 = 0; 
    long long ans[maxn * 7]; 
    void getcvx() { 
    	std::sort(a + 1,a + n + 1,cmp); 
    	for(int i = 1;i <= n;++ i) { 
    		while(tp1 && q1[tp1].a == a[i].a) tp1 --; 
    		while(tp1 > 1 && cross(a[i],q1[tp1]) <= cross(q1[tp1],q1[tp1 - 1]) ) tp1 --; 
    		q1[++ tp1] = a[i]; 
    	} 
    	for(int i = 1;i <= n;++ i) a[i].b = -a[i].b;
    	std::sort(a + 1,a + n + 1,cmp); 
    	for(int i = 1;i <= n;++ i) { 
    		while(tp2 && q2[tp2].a == a[i].a) tp2 --; 
    		while(tp2 > 1 && cross(a[i],q2[tp2]) <= cross(q2[tp2],q2[tp2 - 1]) ) tp2 --; 
    		q2[++ tp2] = a[i]; 
    	} 
    } 
    int main() { 
    	n = read(); q = read(); 
    	for(int i = 1;i <= n;++ i) a[i].a = read(),a[i].b = read(); 
    	getcvx(); 
    	for(int i = 1,x = 1;i <= 32323;++ i)  {
    		while(x < tp1 && cross(q1[x],q1[x + 1]) <= i) ++ x; 
    		ans[i + 32323] = 1ll * q1[x].a * i * i + 1ll * q1[x].b * i; 
    	} 
    	for(int i = 1,x = 1;i <= 32323;++ i) { 
    		while(x < tp2 && cross(q2[x],q2[x + 1]) <= i) ++ x; 
    		ans[32323 - i] = 1ll * q2[x].a * i * i + 1ll * (q2[x].b) * i; 
    	} 
    	for(int i = 1;i <= q;i += 1) { 
    		int k = read(); 
    		printf("%lld
    ",ans[k + 32323]); 
    	} 
    	return 0; 
    } 
    

    B 概率/期望

    题目链接

    题解

    答案可以看做是每一个元素被减的次数之和,可以计算每一个位置被减次数的期望之和
    第一个元素一定被减了(a_1)
    考虑一个位置i,当前有n个元素,那每个元素被减的概率都是(frac{1}{c})
    只关注元素(1)和元素(i),发现操作其他元素对他们没有影响,被减的概率仍相同
    于是这个问题等价于只有两个元素的问题
    对于两个元素的问题,可以看为从((a_1,a_i))出发,每次随机一个位置(-1),知道走到坐标轴上
    若停留在((0,a)),对答案的贡献为(a_i - a),若停留在((a,0)),对答案的贡献为a_i
    可以写出贡献式子

    [sum_{i=0}^{a_i-1}frac{inom{a_1-1+i}{i}}{2^{a_1+i}}i+a_ileft(1-sum_{i=0}^{a_i-1}frac{inom{a_1-1+i}{i}}{2^{a_1+i}} ight) ]

    可以对于(0 - max(ai))做前缀和,前后的概率式等价,最后可以线性计算答案

    code

    #include<cstdio> 
    #include<algorithm> 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' || c > '9') c = getchar(); 
    	while(c <= '9' && c >= '0') x = x * 10 + c - '0' ,c = getchar(); 
    	return x * f; 
    } 
    #define LL long long 
    const int mod = 323232323; 
    const int maxn = 200007; 
    int n,m,a1,a[maxn]; 
    int inv[maxn],inv2[maxn]; 
    int fac[maxn]; 
    inline int fstpow(int x,int k) {
    	int ret = 1; 
    	for(;k;k >>= 1,x = 1ll * x * x % mod) if(k & 1)ret = 1ll * ret * x % mod; 
    	return ret; 
    } 
    inline int C(int n,int m) { 
    	return (1ll * fac[n] * inv[m] % mod) * inv[n - m] % mod; 
    } 
    void pre() {
    	fac[1] = fac[0] = 1; 
    	for(int i = 2;i <= m;++ i) fac[i] = 1ll * fac[i - 1] * i % mod; 
    	inv[m] = fstpow(fac[m],mod - 2); 
    	for(int i = m - 1;~ i;-- i) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod; 
    	//inv[2^i]
    	int t = fstpow(2,mod - 2); inv2[0] = 1; 
    	for(int i = 1;i <= m;++ i) inv2[i] = 1ll * inv2[i - 1] * t % mod; 
    } 
    inline void add(int &x,int y) { 
    	x = x + y >= mod ? x + y - mod : x + y; 
    } 
    int p[maxn],f[maxn]; 
    int main() { 
    	n = read();int mx = 0; 
    	for(int i = 1;i <= n;++ i) a[i] = read(),mx = std::max(mx,a[i]);  
    	a1 = a[1], m = a1 + mx; 
    	pre(); 
    	p[0] = inv2[a1]; 
    	for(int i = 1;i <= m;++ i) { 
    		p[i] = 1ll * C(a1 + i - 1,i) * inv2[a1 + i] % mod; 
    		f[i] = 1ll * i * p[i] % mod; 	
    		add(p[i],p[i - 1]); 
    		add(f[i],f[i - 1]); 
    	} 
    	int ans = a1; 
    	for(int i = 2;i <= n;++ i) {
    		int t = (f[a[i]] + 1ll * a[i] * (mod + 1 - p[a[i]]) % mod) % mod; 
    		add(ans,t); 
    	} 
    	printf("%d
    ",ans); 
    	
    	return 0; 
    } 
    

    C

    题目链接

    题解

    code

  • 相关阅读:
    迭代器模式-Iterator
    kubernetes之一 k8s基本概念
    多线程中的异常处理
    MySQL高可用集群方案
    RabbitMQ的集群模式
    多线程中如何取消任务
    公钥、私钥、摘要、数字签名、证书
    将Ubuntu系统迁移到SSD固态操作
    Java线程的状态和状态转换
    Ubuntu18.04系统和软件安装记录
  • 原文地址:https://www.cnblogs.com/sssy/p/9577018.html
Copyright © 2020-2023  润新知