zr2019暑期高端峰会AB组day7
dls的比赛好duliu啊
A. 松
- 搜索加优化,长度小于等于16的打表预处理
- 做一个位序逆置换,就变得跟蝴蝶操作一样,每次我们用两个压位的二进制数做一次位运算即可
B. 集合
- 赛场上很快就会了一个 n 3 n^3 n3的做法,枚举最大差,枚举最小差,枚举取多少个数,利用差分后的数组,等于求不定方程解的个数,60分,后来才知道这个做法应该是80分的,枚举取多少个数是有限制的,复杂度 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n),好的,不好好算复杂度就挂了20分
- 枚举最小差i,选了j个数,复杂度O(nlogn),现在考虑如何O(1)算出知最小差和数的个数的贡献,即 ∑ i ∗ 最 大 差 ∗ 方 案 数 = ∑ i ∗ ( m x − m n ) ∗ 方 案 数 = i ∗ ( ∑ m x ∗ 方 案 数 − ∑ m n ∗ 方 案 数 ) \sum i*最大差*方案数=\sum i*(mx-mn)*方案数=i*(\sum mx*方案数-\sum mn*方案数) ∑i∗最大差∗方案数=∑i∗(mx−mn)∗方案数=i∗(∑mx∗方案数−∑mn∗方案数)
- 接下来推式子算 ∑ m n ∗ 方 案 数 \sum mn*方案数 ∑mn∗方案数,枚举最小值 c c c
∑ c = 1 n − ( i − 1 ) ( j − 1 ) ( n − ( i − 1 ) ( j − 1 ) − c j − 1 ) ∗ c \sum_{c=1}^{n-(i-1)(j-1)} \tbinom{n-(i-1)(j-1)-c}{j-1} *c c=1∑n−(i−1)(j−1)(j−1n−(i−1)(j−1)−c)∗c
- 经过一波化简最小值贡献等于 ( n − ( i − 1 ) ( j − 1 ) + 1 j ) \tbinom{n-(i-1)(j-1)+1}{j} (jn−(i−1)(j−1)+1)
- 最大值可以和最小值一一对应,对称着来等于 ( n + 1 ) ∗ 方 案 数 − 最 小 值 贡 献 (n+1)*方案数-最小值贡献 (n+1)∗方案数−最小值贡献
- 得 ( n + 1 ) ( n − ( i − 1 ) ( j − 1 ) j ) − 2 ( n − ( i − 1 ) ( j − 1 ) + 1 j + 1 ) (n+1)\tbinom{n-(i-1)(j-1)}{j}-2\tbinom{n-(i-1)(j-1)+1}{j+1} (n+1)(jn−(i−1)(j−1))−2(j+1n−(i−1)(j−1)+1)
C. 最短路
- dls:到了今天最简单的题
- 这题发现通过的桥并不是很多,可以把关键桥建出来跑最短路,也可以直接贪心地,向内向外跳
- 感觉好麻烦的样子,不写了不写了
T2赛场代码
#include<bits/stdc++.h>
#define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
#define For(i,a,b) for (register ll i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
using namespace std;
typedef long long ll;
const int N=5050;
ll n,mod,pre[N],inv[N],ans=0;
inline ll read()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return f*x;
}
inline ll qpow(ll a,ll b)
{
ll ret=1;
while (b)
{
if (b&1) ret=ret*a%mod;
b>>=1;
a=a*a%mod;
}
return ret;
}
inline void init()
{
pre[0]=1;
FOR(i,1,n) pre[i]=pre[i-1]*i%mod;
inv[n]=qpow(pre[n],mod-2);
For(i,n-1,0) inv[i]=inv[i+1]*(i+1)%mod;
return;
}
inline ll C(ll a,ll b)
{
if (b<0||a<0) return 0;
if (a<b) return 0;
ll ret=pre[a]*inv[b]%mod*inv[a-b]%mod;
return ret;
}
int main()
{
n=read(),mod=read();
init();
FOR(mx,1,n-1)
{
FOR(mn,1,mx)
{
ll tmp=0;
FOR(k,1,n)
{
tmp=(tmp+C(mx-k*(mn-1)-1,k-1)-C(mx-k*(mn-1)-k-1,k-1)+mod)%mod;
}
ans=(ans+tmp*(n-mx)%mod*mx%mod*mn%mod)%mod;
}
}
printf("%lld\n",ans);
return 0;
}
T2赛后代码
#include<bits/stdc++.h>
#define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
#define For(i,a,b) for (register ll i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll n,mod,pre[N],inv[N],ans=0,tmp1=0,tmp2=0;
inline ll read()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return f*x;
}
inline ll qpow(ll a,ll b)
{
ll ret=1;
while (b)
{
if (b&1) ret=ret*a%mod;
b>>=1;
a=a*a%mod;
}
return ret;
}
inline void init()
{
pre[0]=1;
FOR(i,1,n+1) pre[i]=pre[i-1]*i%mod;
inv[n+1]=qpow(pre[n+1],mod-2);
For(i,n,0) inv[i]=inv[i+1]*(i+1)%mod;
return;
}
inline ll C(ll a,ll b)
{
if (b<0||a<0) return 0;
if (a<b) return 0;
ll ret=pre[a]*inv[b]%mod*inv[a-b]%mod;
return ret;
}
int main()
{
n=read(),mod=read();
init();
for (register int i=1;i<n;i++)
for (register int j=2;i*(j-1)<n;j++)
ans=(ans+(n+1)*C(n-(i-1)*(j-1),j)%mod-2*C(n-(i-1)*(j-1)+1,j+1)%mod+mod)%mod;
printf("%lld\n",ans);
return 0;
}