前言
前天网上打的比赛了。。
由于实力不够,变成手速场。。
最终结果
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<y且a[y]>=x且a[x]>=y
x
<
y
且
a
[
y
]
>=
x
且
a
[
x
]
>=
y
让y单调递减地询问,那么就可以让合法的x放入,最后查询即可
这个可以用树状数组维护
G
一开始想错方向了
想到了这样一个式子
显然只需要求后面这系数就可以了
但是这样要求某一列的斯特林数,不可做。。(至少我不会)
于是看了题解
我的方法是暴力枚举这个点所在的联通块的大小
但题解是考虑到,如果有一个点 j j 和在一个联通块
那么 i i 的就会被多加一次
考虑这个就好做了
那么对于每一个点的系数就是
这样就只需要求两个斯特林数
直接同通项公式,O(m)来求就可以了
考虑到这题我不会,于是给出代码
其实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;
}