站外题求助
  • 板块学术版
  • 楼主wyf_sinon
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/9 20:29
  • 上次更新2024/7/9 21:54:02
查看原帖
站外题求助
540177
wyf_sinon楼主2024/7/9 20:29

题意大概为每人都有排名(比他高的人数+1)与能力 拿到书本后能力变为t倍,一共k本书,问每个人排名不变的方案数(思路见代码注释 很详细//xyd的ID貌似为4646

下面是代码(赛时思路(正解但是pts10)求调栓Q)

//逆元?已经不会写力
//exgcd(a,x)=exgcd(x,a%n)=1 (mod n )
//a=t1*n+p1
//a*x=1 (mod n)
//t1*n*x+p1*x=1 
//消愁 赛时想手推exgcd 没推出来
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10,MOD=1e9+7;
int n,k,t;
int w[N];
int p[N];
int ans;
int jie[N];
struct s
{
    int w;
    int index;
}a[N],b[N];
int qpow(int a,int b)//MOD为质数 费马小定理求逆元
{
    int res=1;
    a=(a%MOD+MOD)%MOD;
    while(b)
    {
        if(b&1) res=res*a%MOD;
        a=a*a%MOD;
        b>>=1;
    }
    return res;
}
void solve1()
{
    for(int i=1;i<=n;i++)
    {
    	//no发给自己
    	ans=0;
    	int l=1,r=n;
	    while(l<=r)
	    {
	        int mid=l+r>>1;
	        if(b[mid].w>w[i]) l=mid+1;
	        else r=mid-1;//b_mid<=w[i]
	    }
	    int xx=l-2;//高于自己的 因为自己肯定比自己高所以-2
	    int all=p[i]-1+(n-xx-1);//C(all,k)
	    ans=(ans+jie[all]*qpow(jie[k],MOD-2)%MOD*qpow(jie[all-k],MOD-2)%MOD)%MOD;
	    //发给自己
	    int L=1,R=n;
	    while(L<=R)
	    {
	    	int mid=L+R>>1;
	    	if(a[mid].w>w[i]*t) L=mid+1;
	    	else R=mid-1;
		}
		int X=L-1;//高于自己的
		int del=(p[i]-1)-X;//被超越的
		int al=n-del-1,Y=k-1-del;//C(al,y)
		if(Y==0) ans=(ans+1)%MOD;
		else if(k-1-del>0) ans=(ans+jie[al]*qpow(jie[Y],MOD-2)%MOD*qpow(jie[al-Y],MOD-2)%MOD )%MOD;
		printf("%lld\n",ans%MOD);
	}
}
bool cmp(s a,s b)
{
    return a.w>b.w;
}
signed main()
{
	scanf("%lld%lld%lld",&n,&k,&t);
	jie[0]=1;
	for(int i=1;i<=n;i++) jie[i]=(jie[i-1]*i)%MOD;
    for(int i=1;i<=n;i++) scanf("%lld",&a[i].w),a[i].index=i,w[i]=a[i].w;
    sort(a+1,a+1+n,cmp);
    int lst=0;
    for(int i=1;i<=n;i++) 
    {
        b[i].index=a[i].index;
        b[i].w=a[i].w*t;
        p[a[i].index]=lst+1;
        if(a[i].w!=a[lst].w) lst++;
    }
    if(k==n)
    {
        for(int i=1;i<=n;i++) puts("1");
        exit(0);
    }
    solve1();
}
//不发给自己 发给排名比自己高的 or 乘t不超过自己的 组合
//发给自己 要保证发给被自己超越的人 剩下的取组合
//如何高效寻找排名 先排名 再建立×t的集合 互相找?

思路是对的(和正解一样),甚至方法都最优(?目前看到唯一且最优吧),但是实现上可能哪里出了问题 能过n为100的样例 但是拿10pts

玄关

2024/7/9 20:29
加载中...