250603 模拟赛

分数:\(20+0+0=20\)

比赛开始半个小时才知道有比赛求放过/也没少睡啊但是非常困,看了一下 T1 感觉容斥,而且非常的简单,然后写了一会发现思路有很大问题,然后不会了,然后断定大家都不会 T1,去看没看完的 T2,发现这个题意非常的复杂,T3 也是有点那啥的题。但是因为太困可能没发挥吧?


T1 钢铁是怎样炼成的

\(x_1+x_2+...+x_m=n\) 的方程,称一组解的价值为 \(\max x_i\),随机选择一组解,求价值的期望。

一眼就知道要枚举最大值,然后求出有多少种划分可以达到这个最大值再除以总方案数,显然容斥。不知道当时怎么想的啊,就是先选出来某一个 \(x=i\),再正常枚举钦定多少个位置,但是这样算答案是非常的奇怪,因为有顺序之类的问题需要考虑。

考虑设 \(f_i\) 为最大值 \(\ge i\) 的划分方案数,显然需要求的是 \(\sum i\times(f_i-f_{i+1})\)\(f_i\) 正常容斥去求就可以了。然后感觉复杂度可能是 \(O(n^2)\) 的,但是发现方案数到钦定 \(\lfloor \frac{n}{i}\rfloor+1\) 个超过的时候方案数就会变成 \(0\),所以总的复杂度就是调和级数 \(O(n\ln n)\)

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
	int t=0;char h=getchar();
	while(!isdigit(h))h=getchar();
	while(isdigit(h))t=(t<<1)+(t<<3)+(h^48),h=getchar();
	return t;
}
void write(int x)
{
	if(x>9)write(x/10);putchar(x%10+'0');
}
const int mod=1e9+7;
const int N=1e6+10;
ll quikp(ll a,int b)
{
	ll res=1;
	while(b)(b&1)&&((res*=a)%=mod),(a*=a)%=mod,b>>=1;
	return res;
}
ll fac[N],inv[N];
inline ll c(int n,int m)
{
	return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
ll f[N],p[2],ans=0;
int n,m;
int main()
{
	n=read();m=read();fac[0]=1;p[0]=mod-1;p[1]=1;
	for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;
	inv[n]=quikp(fac[n],mod-2);
	for(int i=n-1;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
	for(int i=n-m+1,lmt=ceil(n/m);i;i--)
	{
		ll res=0;
		for(int j=1,t=n-(i-1);t>=m&&j<=m;j++,t-=i-1)(res+=p[j&1]*c(t-1,m-1)%mod*c(m,j)%mod)%=mod;
		f[i]=res;
		(ans+=i*((f[i]+mod-f[i+1])%mod)%mod)%=mod;
	}
	(ans*=quikp(c(n-1,m-1),mod-2))%=mod;
	write(ans);
	return 0;
}

T2 字符串

抽象的题面


T3 平衡

构造 \(m\) 个二元组 \((x_i,y_i)\),使得 \(\sum x_i=A,\sum y_i=B\),前 \(k\) 个二元组两两不同,最大化 \(k\)\(x_i,y_i\in N\)

posted @ 2025-06-05 15:43  baiguifan  阅读(30)  评论(0)    收藏  举报