• qbxt 10 月模拟赛 Day7


    A

    贪心删除出现次数最少的数。

    #include <bits/stdc++.h>
    
    #define fi first
    #define se second
    #define db double
    #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
    
    const int MAXN = 2e5 + 5;
    int n,a[MAXN],b[MAXN],k;
    
    int main(){
        scanf("%d%d",&n,&k);
        FOR(i,1,n) scanf("%d",a+i),b[a[i]]++;
        int t = 0;FOR(i,1,n) t += (b[i] != 0);
        std::sort(b+1,b+n+1);
        int ans = 0;
        FOR(i,1,n){
            if(t <= k) break;
            if(!b[i]) continue;
            ans +=  b[i];t--;
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    B

    逆序对期望,根据期望的线性性转成考虑每一对数的期望,由于权值是 (0/1),现在变成了对于一对数 ((x,y)),计算是一对逆序对的概率。

    我们设 (x<y),那么一定是先共同经过若干轮都没有被选中,然后在第 (i) 轮选中了 (y) 但没有选中 (x),之后若干轮后选了 (x);我们枚举 (i) 可以得到概率:

    [egin{aligned} sum_{i=1}^{infty} (1-p)^{i-1}p (1-p)^i &= p(1-p)sum_{i=0}^{infty}(1-p)^{2i}\ &= p(1-p)frac{1}{1-(1-p)^2} end{aligned} ]

    注意到对数有 (inom n 2) 个,所以答案是 (inom n 2 p(1-p)frac{1}{1-(1-p)^2})

    #include <bits/stdc++.h>
    
    #define fi first
    #define se second
    #define db double
    #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
    
    const int ha = 998244353;
    const int inv2 = 499122177;
    
    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(){
        int n,x,y;scanf("%d%d%d",&n,&x,&y);
        int p = 1ll*x*qpow(y)%ha;
        int ans = 1ll*n*(n-1)%ha*inv2%ha;
        int t = (1+ha-p)%ha;t = 1ll*t*t%ha;
        t = (1+ha-t)%ha;t = qpow(t);
        ans = 1ll*ans*t%ha;
        ans = 1ll*ans*(1+ha-p)%ha;
        ans = 1ll*ans*p%ha;
        printf("%d
    ",ans);
        return 0;
    }
    

    C

    提供我考场的思路和标程思路,我的思路应该是正规 NOIP 思路((虽然代码本质是一样的

    首先我们考虑有以下恒等式:

    [x^k = sum_{i_1=1}^x sum_{i_2=1}^x cdotssum_{i_k=1}^x 1 ]

    所以对于一条路径的 (x^k) 可以理解成有序可重地选出 (k) 条边,所以一个暴力dp的思想就是设 (f_{v,i}) 表示从 (1)(v) 选了 (i) 个边的方案数,每次转移 (O(k)) 枚举当前边被选了 (j) 次,系数是 (inom{k-i}{j}),这样复杂度是 (O(mk^2)) 的。

    优化:我们可以考虑每条路径的系数只和选了多少条不同的边有关,假设选了 (m) 条不同的边,系数和大概是这样的一个东西:

    [sum_{x_1 + x_2 + ldots + x_m = k} inom{k}{x_1,x_2,ldots,x_m} ]

    这个东西我考试的时候写了 (k^3) dp 出来的,但是可以发现实际上它是将 (k) 个有标号小球放进 (m) 个有标号小球,要求非空的方案数,也就是 (left{^k_m ight}m!)

    所以我们 dp 的时候只需要求出 (f_{v,i})(v) 点,选了 (i) 条边的方案数,转移直接枚举当前边是否选,(O(mk + k^2))

    题解做法(一点点省选知识):考虑恒等式:

    [x^k = sum_{i=0}^k left{^k_i ight}x^{underline k} = sum_{i=0}^k left{^k_i ight}inom x k k! ]

    所以我们只需要求出 (f_{v,i}) 表示到 (v) 点,所有路径的 (inom x k) 的和即可,注意到有 (inom n m = inom {n-1}{m} + inom {n-1}{m-1}),转移的时候只要枚举当前边是否选就行了。

    对于这种只能从一个点出发的 DAG 游走,只需要初始化起点然后正常拓扑排序即可。

    #pragma GCC optimize("Ofast")
    #include <bits/stdc++.h>
    
    #define fi first
    #define se second
    #define db double
    #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
    
    const int MAXN = 1e5 + 5;
    const int MAXK = 500 + 5;
    const int ha = 998244353;
    
    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;
    }
    
    struct Edge{
        int to,nxt;
    }e[MAXN<<1];
    bool vis[MAXN];
    int head[MAXN],cnt,deg[MAXN];
    
    inline void adde(int u,int v){
        e[++cnt] = (Edge){v,head[u]};head[u] = cnt;
        deg[v]++;
    }
    
    inline void add(int &x,int y){
        (x += y);if(x >= ha) x -= ha;
    }
    
    int f[MAXN][MAXK];
    int n,m,k;
    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 < 0 || m < 0 || n < m) return 0;
        return 1ll*fac[n]*inv[m]%ha*inv[n-m]%ha;
    }
    
    int g[MAXK][MAXK];
    // i个变量,和为 j
    
    int main(){
        prework();
        read(n);read(m);read(k);
        g[0][0] = 1;
        FOR(i,1,k){
            FOR(j,i,k){
                FOR(x,1,j){
                    add(g[i][j],1ll*g[i-1][j-x]*C(k-(j-x),x)%ha);
                }
            }
        }
        FOR(i,1,m){
            int u,v;read(u);read(v);
            adde(u,v);
        }
        std::queue<int> q;
        q.push(1);vis[1] = 1;
        while(!q.empty()){
            int v = q.front();q.pop();
            for(int i = head[v];i;i = e[i].nxt){
                if(vis[e[i].to]) continue;
                q.push(e[i].to);vis[e[i].to] = 1;
            }
        }
        FOR(v,1,n){
            if(!vis[v]){
                for(int i = head[v];i;i = e[i].nxt){
                    deg[e[i].to]--;
                }
            }
        }
        q.push(1);
        f[1][0] = 1;
    //    assert(deg[1]==0);
        FOR(i,1,n) vis[i] = 0;
        while(!q.empty()){
            int v = q.front();q.pop();vis[v] = 1;
            for(int i = head[v];i;i = e[i].nxt){
                FOR(x,0,k){
                    if(!f[v][x]) continue;
                    FOR(y,0,std::min(1,k-x)){
                        add(f[e[i].to][x+y],f[v][x]);
                    }
                }
                if(!--deg[e[i].to]) q.push(e[i].to);
            }
        }
        FOR(i,1,n){
            int ans = 0;
            FOR(j,1,k){
                add(ans,1ll*f[i][j]*g[j][k]%ha);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    D

    曼哈顿距离两维独立考虑,一维上给你若干个点,求一个点满足曼哈顿距离和最小是经典问题:只需要取中位数即可。

    那么对于这个题我们肯定要二分中位数 (x),然后变成了计算有多少个交点满足横坐标 (leq x)(求纵坐标的时候只需要求一下反函数即可)。

    赛时思路:

    按照斜率排序,考虑 (i,j) 两条直线((i < j))的交点横坐标是 (frac{b_i-b_j}{k_j-k_i}),也就是要判断是否 (frac{b_i-b_j}{k_j-k_i} leq x Rightarrow b_i+k_ix leq k_jx+b_j),离散化+树状数组或者归并排序求顺序对都可以。

    题解思路:

    考虑我们按照 (-infty) 的值排序,观察走到 (x) 的变化:如果有交点就会产生一对逆序对。

    所以我们只需要一开始按照 (-infty) 的值编号,每次 check 的时候按照 (x) 的位置的 (y) 值排序,逆序对就是答案。

    #pragma GCC optimize("Ofast")
    #include <bits/stdc++.h>
    
    #define fi first
    #define se second
    #define db double
    #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
    
    const int MAXN = 40000+5;
    const int EPS = 1e-9;
    
    inline int sgn(double x){
        if(std::fabs(x) <= EPS) return 0;
        if(x < 0) return -1;
        return 1;
    }
    
    int n;
    int aa[MAXN],bb[MAXN],cc[MAXN];
    std::pair<double,double> seg[MAXN];
    double a[MAXN];
    int c[MAXN];
    
    struct BIT{
        int tree[MAXN];
        #define lowbit(x) ((x)&(-(x)))
    
        inline void add(int pos,int x){
            while(pos < MAXN){
                tree[pos] += x;
                pos += lowbit(pos);
            }
        }
    
        inline int query(int pos){
            int res = 0;
            while(pos){
                res += tree[pos];
                pos -= lowbit(pos);
            }
            return res;
        }
    }bit;
    
    inline bool chk(double x){ // <=x 的交点个数是否超过一半
        LL ans = 0;
        std::sort(seg+1,seg+n+1);
        FOR(i,1,n) a[i] = seg[i].se+x*seg[i].fi;
        std::vector<double> S;
        FOR(i,1,n) S.pb(a[i]);
        std::sort(all(S));S.erase(std::unique(all(S)),S.end());
        FOR(i,1,n) c[i] = std::lower_bound(all(S),a[i])-S.begin()+1;
        CLR(bit.tree,0);
        FOR(i,1,n){
            ans += bit.query(c[i]);
            bit.add(c[i],1);
        }
        LL lim = 1ll*n*(n-1)/2;
    //    DEBUG(ans);
        return ans >= lim - ans;
    }
    
    inline double work(){
        std::sort(seg+1,seg+n+1);
        double l = -1e9,r = 1e9,ans=0;
        FOR(i,1,70){
            double mid = (l + r)/2.0;
            if(chk(mid)) ans = mid,r = mid;
            else l = mid;
        }
        return ans;
    }
    
    int main(){
        scanf("%d",&n);
        FOR(i,1,n){
            scanf("%d%d%d",aa+i,bb+i,cc+i);
            seg[i] = MP(-1.0*(1.0*aa[i]/bb[i]),1.0*cc[i]/bb[i]);
        }
        printf("%.6f ",work());
        FOR(i,1,n){
            seg[i] = MP(-1.0*(1.0*bb[i]/aa[i]),1.0*cc[i]/aa[i]);
        }
     //   DEBUG(chk(-4905.877264));
     //   exit(0);
        printf("%.6f
    ",work());
        return 0;
    }
    
  • 相关阅读:
    pgsql批量新增覆盖原表数据
    乘风破浪,遇见最美Windows 11之新微软商店(Microsoft Store)生态 Wondershare HiPDF正式登陆Teams应用市场
    乘风破浪,遇见未来新能源汽车(Electric Vehicle)之特斯拉掀起CTC技术浪潮,5大车企扎堆跟进,想要干掉电池组
    时光卷轴,IT启示录2022年6月刊
    乘风破浪,遇见最美Windows 11之现代Windows桌面应用开发 微软跨平台UI框架.NET MAUI,基于.NET 6构建的通用框架
    HTTP编码和解码与基本认证
    HTTPS&SPDY&HTTP2&QUIC&HTTP3
    HTTP报文结构
    HTTP内容协商机制和断点续传
    HTTP Web安全
  • 原文地址:https://www.cnblogs.com/rainair/p/14305577.html
Copyright © 2020-2023  润新知