zoukankan      html  css  js  c++  java
  • [PKUSC2018]真实排名

    [PKUSC2018]真实排名

    题目大意:

    (n(nle10^5))个人,每个人有一个成绩(A_i(0le A_ile10^9))。定义一个人的排名为(n)个人中成绩不小于他的总人数。现在恰好有(k)个人的成绩翻倍。问对于每个人,有多少种情况满足这个人的排名不变。

    思路:

    排名不变的情况不外乎两种:

    1. (A_i)本身不翻倍,且满足(lfloorfrac{A_i+1}2 floorle A_j<A_i)(A_j)均不翻倍。
    2. (A_i)本身翻倍,且满足(A_ile A_j<2A_i)(A_j)均翻倍。

    (A_{1sim n})进行排序,设排序后的数组为(tmp)。令:

    • p=std::lower_bound(&tmp[1],&tmp[n]+1,(a[i]+1)/2)-tmp-1
    • q=std::lower_bound(&tmp[1],&tmp[n]+1,a[i])-tmp
    • r=std::lower_bound(&tmp[1],&tmp[n]+1,a[i]*2)-tmp+!a[i]

    其中(p)-1是为了方便将(A_i)本身也算入不翻倍的部分,而(r)+!a[i]是考虑(A_i=0)的情况,将(A_i)自身算入翻倍的部分。

    显然,对于第一种情况,方案数为(inom{n-q+p}k);对于第二种情况,方案数为(inom{n-r+q}{k-r+q})

    组合数可以直接预处理阶乘及阶乘逆元,剩下主要是排序和二分。时间复杂度(mathcal O(nlog n))

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    typedef long long int64;
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    const int N=1e5+1,mod=998244353;
    int a[N],tmp[N],fact[N],factinv[N];
    void exgcd(const int &a,const int &b,int &x,int &y) {
    	if(!b) {
    		x=1,y=0;
    		return;
    	}
    	exgcd(b,a%b,y,x);
    	y-=a/b*x;
    }
    inline int inv(const int &x) {
    	int ret,tmp;
    	exgcd(x,mod,ret,tmp);
    	return (ret%mod+mod)%mod;
    }
    inline int C(const int &n,const int &m) {
    	if(n<m||n<0||m<0) return 0;
    	return (int64)fact[n]*factinv[m]%mod*factinv[n-m]%mod;
    }
    int main() {
    	const int n=getint(),k=getint();
    	for(register int i=1;i<=n;i++) {
    		tmp[i]=a[i]=getint();
    	}
    	std::sort(&tmp[1],&tmp[n]+1);
    	for(register int i=fact[0]=1;i<=n;i++) {
    		fact[i]=(int64)fact[i-1]*i%mod;
    	}
    	factinv[n]=inv(fact[n]);
    	for(register int i=n;i;i--) {
    		factinv[i-1]=(int64)factinv[i]*i%mod;
    	}
    	for(register int i=1;i<=n;i++) {
    		const int p=std::lower_bound(&tmp[1],&tmp[n]+1,(a[i]+1)/2)-tmp-1;
    		const int q=std::lower_bound(&tmp[1],&tmp[n]+1,a[i])-tmp;
    		const int r=std::lower_bound(&tmp[1],&tmp[n]+1,a[i]*2)-tmp+!a[i];
    		printf("%d
    ",(C(n-q+p,k)+C(n-r+q,k-r+q))%mod);
    	}
    	return 0;
    }
    
  • 相关阅读:
    2017浙江工业大学-校赛决赛 猜猜谁是我
    2017浙江工业大学-校赛决赛 竹之书
    2017浙江工业大学-校赛决赛 小M和天平
    2017"百度之星"程序设计大赛
    2017"百度之星"程序设计大赛
    2017"百度之星"程序设计大赛
    2017"百度之星"程序设计大赛
    2015-2016机器人操作系统(ROS)及其应用暑期学校资料汇总 ROS Summer School 持续更新
    2016“智能无人系统”暑期学校总结
    ROS_Kinetic_20 ROS基础补充
  • 原文地址:https://www.cnblogs.com/skylee03/p/9154048.html
Copyright © 2011-2022 走看看