A层邀请赛3
日常垫底,赛个球
A. 玩个球
组合数,搞了个傻逼性质在那乱转移,结果还是只有的分,有趣的是中间交的一份码过了的,但是不是最后一次提交。。
正解
表示放了个白球,有个颜色放完的方案数,主要思想在枚举剩余位置的第一个放啥
考虑放白球,直接转移
放颜色,先选一个颜色,此时剩下 个,再用组合数求个数放在后面的方案数
code
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 2005;
const int mod = 1e9 + 7;
int fac[maxn * maxn], inv[maxn * maxn];
int qpow(int x, int y){
int ans = 1;
for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
return ans;
}
void pre(int mx){
fac[0] = 1; for(int i = 1; i <= mx; ++i)fac[i] = 1ll * fac[i - 1] * i % mod;
inv[mx] = qpow(fac[mx], mod - 2); for(int i = mx - 1; i; --i)inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
inv[0] = 1;
}
int C(int n, int m){return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;}
int n, k, f[maxn][maxn];
int main(){
scanf("%d%d", &n, &k);
pre(n * k);
for(int i = 1; i <= n; ++i){
f[i][0] = 1;
for(int j = 1; j <= i; ++j){
f[i][j] = (f[i - 1][j] + 1ll * f[i][j - 1] * (n - j + 1) % mod * C(n * k - (j - 1) * (k - 1) - i - 1, k - 2) % mod) % mod;
}
}
printf("%d\n",f[n][n] % mod);
return 0;
}
B. 序列
刚讲过类似的常规套路就忘了。。。。
线段树维护的值,记录上一个与当前值相同的数的位置, 然后就是类似的项链的区间修改,查询最小值,为就
另一种思路,每次找到区间中只出现一次的数,然后拆分问题为该数左右两边的区间
暴力找复杂度不对,考虑启发式,从两边同时向里找,这样复杂度就是级别了
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200055;
inline int read(){
int x = 0; char c = getchar();
while(c < '0' || c > '9')c = getchar();
do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c >='0' && c <= '9');
return x;
}
int n, a[maxn], b[maxn], pre[maxn], nxt[maxn], rm[maxn];
bool solve(int l, int r){
if(l >= r)return true;
int len = r - l + 1;
int mx = (len + 1) >> 1;
int pos = -1;
for(int i = 1; i <= mx; ++i){
int nl = l + i - 1, nr = r - i + 1;
if(pre[nl] < l && nxt[nl] > r){pos = nl;break;}
if(pre[nr] < l && nxt[nr] > r){pos = nr;break;}
}
if(pos == -1)return false;
return solve(l, pos - 1) && solve(pos + 1, r)
}
inline bool work(){
n = read();
for(int i = 1; i <= n; ++i)a[i] = read();
for(int i = 1; i <= n; ++i)b[i] = a[i];
sort(b + 1, b + n + 1);
for(int i = 1; i <= n; ++i)a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
for(int i = 1; i <= n; ++i)pre[i] = 0;
for(int i = 1; i <= n; ++i)nxt[i] = 0;
for(int i = 1; i <= n; ++i)rm[i] = 0;
for(int i = 1; i <= n; ++i){
pre[i] = rm[a[i]];
nxt[rm[a[i]]] = i;
rm[a[i]] = i;
}
for(int i = 1; i <= n; ++i)nxt[rm[a[i]]] = n + 1;
return solve(1, n);
}
int main(){
int T = read();
for(int i = 1; i <= T; ++i)if(work())printf("non-boring\n");else printf("boring\n");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】