7.13 T2 Shit 题(shit)

【题目描述】 某一天,小𝐶打开了一场𝐴𝐶𝑀比赛,准备来一场爱的大训练。 这 场𝐴𝐶𝑀比赛一共有𝑁道题。 小𝐶已经调查到自己能用𝑇𝑖 毫秒来解决第𝑖道题。 小𝐶已经用过各种各样的开题姿势切了无数场𝐴𝐶𝑀,这次他决定 使用一种新的姿势。 1.首先,小𝐶将会随机的打开𝐾道题。 2.小𝐶会选择𝐾道题中所需的时间最少的一道题并解决它。 3.如果还有没有打开的题目,小𝐶会再随机的打开一道没打开过的 题。 4.若小𝐶还没有解决所有的题目,则回到 2。 小𝐶并不关注某种情况下的罚时,他只想知道在所有𝑁!种情况下 自己的罚时总和。 定义一次比赛中的罚时为所有问题的被解决时刻之和,小𝐶是个优 秀的代码 手所以他并不会产生其他的罚时。

【输入格式】 从文件 shit.in 中读入数据。 第一行二个整数𝑁,K. 第二行𝑁个整数描述𝑇𝑖。

【输出格式】 输出到文件 shit.out 中。 一行,输出答案对 109 + 7 取模的值。

【样例输入】

4 3 1 3 2 1

【样例输出】 336

【数据范围】 对于 10%的数据,𝑁 ≤ 8。 对于 20%的数据,𝑁 ≤ 15。 对于 30%的数据,𝑁 ≤ 30。 对于 50%的数据,𝑁 ≤ 100。 对于 100%的数据,𝑁 ≤ 300,1 ≤ 𝑇𝑖 ≤ 1e6

 

sol:求数字i在前j位被取走的方案数,然后差分一下就是第i个数字在第j位被取走的方案了

标程有讲解

#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N=305,mo=1e9+7;
int n,m,k,i,x,j,a[N],la,ans;
int C[N][N],fact[N];
void init(){
    for (i=0;i<=n;i++) for (C[i][0]=1,j=1;j<=i;j++)
        C[i][j]=(C[i-1][j]+C[i-1][j-1])%mo;
    for (fact[0]=1,i=1;i<=n;i++)
        fact[i]=(ll)fact[i-1]*i%mo;
}
/*
    做第i轮时有i+k-1个数
    会取走前i小的数
    或者说前i小的数一定会被取走
    上式中
    m为当前第x轮的数个数
    当大于i的数个数大于等于m-x时
    i在前x小中
    得出的sum为i在前x轮被取走的情况数 
*/
int main(){
    freopen("shit.in","r",stdin);
    freopen("shit.out","w",stdout);
    scanf("%d%d",&n,&k);
    for (i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);init();
    for (i=1;i<=n;i++) for (x=1,la=0;x<=n;x++){
        m=min(n,x+k-1);int sum=0;
        for (j=m-x;j<m;j++)
            sum=(sum+(ll)C[n-i][j]*C[i-1][m-1-j])%mo;
        sum=(ll)sum*fact[m]%mo*fact[n-m]%mo;
        ans=(ans+(ll)(sum-la+mo)*(n+1-x)*a[i])%mo;
        la=sum;
    }
    printf("%d",ans);
}
bs

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0'); return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=305;
const ll Mod=1000000007;
ll n,m;
ll fac[N],C[N][N];
ll t[N];
inline void Ad(ll &x,ll y) {x+=y; x-=(x>=Mod)?Mod:0;}
int main()
{
    freopen("shit.in","r",stdin);
    freopen("shit.out","w",stdout);
    ll i,j,k,Las,ans=0;
    R(n); R(m); for(i=1;i<=n;i++) R(t[i]);
    fac[0]=1; for(i=1;i<=n;i++) fac[i]=fac[i-1]*i%Mod;
    for(i=0;i<=n;i++) {C[i][0]=1; for(j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%Mod;}
    sort(t+1,t+n+1);
    for(i=1;i<=n;i++) for(j=1,Las=0;j<=n;j++) //第i个数字第j轮
    {
        ll cnt=min(n,m+j-1),Sum=0;
        for(k=cnt-j;k<cnt;k++)//有k个数字比第i个大
        {
            Ad(Sum,C[n-i][k]*C[i-1][cnt-k-1]%Mod);
        }
        Sum=Sum*fac[cnt]%Mod*fac[n-cnt]%Mod;//Sum是第i个数在前j轮被取走的方案数
        Ad(ans,1ll*(Sum-Las+Mod)*(n-j+1)%Mod*t[i]%Mod);//差分一下就是第i个第j轮被取走的,第j~n个要多等t[i]分钟
        Las=Sum;
    }
    Wl(ans);
    return 0;
}
/*
input
4 3
1 3 2 1
output
336
*/
View Code

 

posted @ 2019-07-14 21:39  yccdu  阅读(232)  评论(0编辑  收藏  举报