Educational Codeforces Round 41 (Rated for Div. 2)

前言

前天网上打的比赛了。。
由于实力不够,变成手速场。。
最终结果
rank120左右,做了A,B,C,D,E。G没有做出来,赛后更正了。。
F还没做,但最近也不打算做。。以后再做吧

题解

A

直接看一下哪一个数字出现地最少,输出来即可

B

预处理一些前缀和和后缀和
暴力枚举在哪里叫醒他就可以了

C

考虑到只有4个矩阵,所以我们可以用 4! 4 ! 的时间来枚举排列方案
然后显然最终合法的矩阵只有两种
一种是左上角是0,另外一种是左上角是1
然后枚举完一个暴力check就好了
我一开始dfs都写错了

D

考虑找到一个点x
x满足和1,2不共线
那么只有三种情况
1,2为一条直线
2,x为一条直线
1,x为一条直线
然后暴力判断就可以了

E

容易发现条件等价于
x<ya[y]>=xa[x]>=y x < y 且 a [ y ] >= x 且 a [ x ] >= y
让y单调递减地询问,那么就可以让合法的x放入,最后查询即可
这个可以用树状数组维护

G

一开始想错方向了
想到了这样一个式子

Ans=i=1nw[i]j=1njC(n1,j1)S(nj,k1) A n s = ∑ i = 1 n w [ i ] ∗ ∑ j = 1 n j ∗ C ( n − 1 , j − 1 ) ∗ S ( n − j , k − 1 )

显然只需要求后面这系数就可以了
但是这样要求某一列的斯特林数,不可做。。(至少我不会)
于是看了题解
我的方法是暴力枚举这个点所在的联通块的大小
但题解是考虑到,如果有一个点 j j i在一个联通块
那么 i i w就会被多加一次
考虑这个就好做了
那么对于每一个点的系数就是
这里写图片描述

这样就只需要求两个斯特林数
直接同通项公式,O(m)来求就可以了

S(n,m)=1m!k=0m(1)kCmk(mk)n S ( n , m ) = 1 m ! ∑ k = 0 m ( − 1 ) k C k m ( m − k ) n

考虑到这题我不会,于是给出代码
其实CF的代码都是公布了。。如果想要,去CF拿就可以了
CODE:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const LL N=200005;
LL n,k;
LL w[N];
LL sum=0;
LL JC[N],inv[N];
LL pow (LL x,LL y)
{
    if (y==1) return x;
    LL lalal=pow(x,y>>1);
    lalal=lalal*lalal%MOD;
    if (y&1) lalal=lalal*x%MOD;
    return lalal;
}
LL C (LL x,LL y)
{
    if (x<y) return 0;
//  printf("%I64d %I64d %I64d %I64d %I64d %I64d\n",x,y,JC[x],inv[y],inv[x-y],JC[x]*inv[y]%MOD*inv[x-y]%MOD);
    return JC[x]*inv[y]%MOD*inv[x-y]%MOD;
}
LL s (LL x,LL y)
{
    LL t=1,lalal=0;

    for (int k=0;k<=y;k++)
    {
        lalal=lalal+t*C(y,k)%MOD*pow(y-k,x)%MOD;
        lalal=lalal%MOD;
        t*=(-1);
    }
    lalal=(lalal+MOD)%MOD;
    lalal=lalal*inv[y]%MOD;
//  printf("%I64d %I64d %I64d\n",x,y,lalal);
    return lalal;
}
int main()
{
    //  freopen("a.in","r",stdin);
    scanf("%I64d%I64d",&n,&k);
    JC[0]=1;for (LL u=1;u<=200000;u++) JC[u]=JC[u-1]*u%MOD;
    inv[200000]=pow(JC[200000],MOD-2);
    for (LL u=200000-1;u>=1;u--)    inv[u]=inv[u+1]*(u+1)%MOD;inv[0]=1; 
    for (LL u=1;u<=n;u++)
    {
        scanf("%I64d",&w[u]);
        sum=sum+w[u];
        sum%=MOD;
    }
    if (k==1)
    {
        printf("%I64d\n",sum*n%MOD);
        return 0;
    }
    LL lalal=(s(n,k)+(n-1)*s(n-1,k)%MOD)%MOD;
    printf("%I64d\n",sum*lalal%MOD);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值