前言:CF特有的代码短,思维量大到爆炸

A~C

直接看好朋友Yorg的博客yza的A~C

D:

题意:

给你一个长度为\(n\)的序列\(x,x_{1,2......n},x_i\in[1,n]\),还有一个未知的长度为\(n\)的序列\(y\),两个序列可能由\((x_i,y_i)\)这样的\(n\)对二元组构成一个有\(n\)个点的网格图,或者有\(n\)个点的有向图(边权总为1),你可以通过交互的方式进行两次询问,每次询问两个范围在\(1\)到\(n\)的值,如果代表网格图则给出两点之间的曼哈顿距离,否则给出两点之间在有向图上的最短距离,由此得出\(x\)与\(y\)构成的关系

思路

情况1:

若序列\(x\)至少存在两个大小相同的元素,那么一定存在\(num\in[1,n],num\notin x\),所以我们询问它与其他任意点的值,如果是图,那么最短距离一定是\(0\),否则曼哈顿距离一定不为\(0\)。

情况2:

若序列\(x\)成为了\([1,n]\)的一个排列,那么找到其中大小为\(1,n\)的元素,因为是有向图,所以\(dis(1,n)\)最大也就是\(n-1\),而一旦我们调换起始点和终点,在两次询问下,距离不可能同时为\(n-1\),也就是\(dis(1,n),dis(n,1)\)在只有\(n\)条边的有向图中不可能同时为一,而曼哈顿距离\(m(1,n),m(n,1)\)都一定大于等于1,所以据此判断即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector> void solve(){
int n;
scanf("%d",&n);
std::vector<int> a(n + 1,0);
std::vector<int> sve;
for(int i = 1;i <= n;++i){
int x;
scanf("%d",&x);
++a[x];
sve.push_back(x);
} for(int i = 1;i <= n;++i){
if(a[i] == 0){
int x,y;
printf("? %d %d\n",i,sve[0]);
flush(std::cout);
scanf("%d",&x);
printf("? %d %d\n",sve[0],i);
flush(std::cout);
scanf("%d",&y);
if(x == 0 || y == 0 || x != y){
printf("! A\n");
flush(std::cout);
return;
}else{
printf("! B\n");
flush(std::cout);
return;
}
}
}
int minp = 0,maxp = 0;
for(int i = 0;i < n;++i){
if(sve[i] < sve[minp]) minp = i ;
if(sve[i] > sve[maxp]) maxp = i ;
}
int x,y;
printf("? %d %d\n",minp + 1,maxp + 1);
flush(std::cout);
scanf("%d",&x);
printf("? %d %d\n",maxp + 1,minp + 1);
flush(std::cout);
scanf("%d",&y);
if(x < n - 1 || y < n - 1 || x != y)
{
printf("! A\n");
flush(std::cout);
return;
}else{
printf("! B\n");
flush(std::cout);
return;
}
} int main(){
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}

E:

题意:

我们定义一个长度为\(n\)的序列\(a\)是神奇的,当且仅当:

\[\forall_{i\in[1,n-1]},min_{j = 1}^{i}\{a_i\}\geq mex_{j=i+1}^{n}\{a_{i}\}
\]

此处\(mex\)定义为在该序列集合中不存在的最小的非负整数

我们希望求出序列\(a\)最长神奇子序列的长度,(如果序列\(a\)是序列\(b\)的子序列,则\(a\)可以通过从\(b\)中删除若干(可能为零或全部)元素得到)。

思路:

tips:

1.显然一个没有元素\(0\)的序列的\(mex\)就是\(0\),所以显然,没有元素\(0\)的序列一定是神奇的。

2.若一个序列含有两个0,则其一定不是神奇的

所以思路就很明了了,答案就在\(n-cnt_0\)和\(n-cnt_0+1\)之间,其中\(cnt_0\)表示0的个数,那么第一个方案显然一定存在,考虑第二个,可以证明,如果想要让序列中存在一个\(0\),那么选左边的一定是最优的,然后\(O(n)\)计算是否可行,最后输出答案即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<unordered_map> std::unordered_map<int,bool> exsit;
const int INF = 0x3f3f3f3f;
void solve(){
int n;
scanf("%d",&n);
std::vector<int> a(n + 1);
std::vector<int> pre_min(n + 1);
std::vector<int> pre_mex(n + 1);
pre_min[0] = INF;
bool flag = true,f_ans = true;
int cnt = 0;
for(int i = 1;i <= n;++i){
int x;
scanf("%d",&x);
if(x || (flag && !x)){
a[++cnt] = x;
if(!x){
flag = false;
}
}
} if(flag)
{
printf("%d\n",n);
return;
} for(int i = 1;i <= cnt;++i){
pre_min[i] = std::min(pre_min[i - 1],a[i]);
} exsit.clear();
int tmp_mex = 0;
for(int i = cnt;i >= 1;--i){
exsit[a[i]] = true;
while(exsit[tmp_mex]){
++tmp_mex;
}
pre_mex[i] = tmp_mex;
} for(int i = 1;i < cnt;++i){
if(pre_mex[i + 1] > pre_min[i]){
f_ans = false;
break;
}
}
if(f_ans) printf("%d\n",cnt);
else printf("%d\n",cnt - 1);
} int main(){
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}

F:

题意:

F题题面

所谓不成对不同翻译的不好,其实就是,三个数里面至少有两个相同

思路:

我们考虑构造一些神奇的东西,我们令:

\[pref_i=\oplus_{j=1}^ia_j
\]

即:前i个数的异或和。并且我们发现,在每次操作完后,若依旧满足题意,那么一定有:

\[P\oplus Q\oplus R=pref_i
\]

又因为一定至少有两个数相同,所以一定有一个数等于\(pref_i\),因为相同的两个数异或之后等于0。所以我们令三元组\(\zeta=(P,Q,R)\),若这是一个合法三元组,那么一定形如下面三种情况:

\[(x,x,pref_i)
\]
\[(x,pref_i,x)
\]
\[(pref_i,x,x)
\]

所以这提醒我们使用动态规划的方法求解这个方案数类型的问题。

定义\(f_{i,x}\),表示经过\(i\)次操作后,达到形如\((x,x,pref_i)、
(x,pref_i,x)、
(pref_i,x,x)\)的状态的方案数。

那么\(f_{0,0}=1\)。

现在我们希望用\(f_{i-1,?}\)来更新\(f_{i,x}\),那么我们来分类讨论。想从\(i - 1\)转移过来,无非就3种情况:

\[(x\oplus a_i,x,pref_i)、(x,x\oplus a_i,pref_i)、(x,x,pref_i\oplus a_i)
\]

情况1:\(pref_i\oplus a_i\)

那么显然上一个三元组就是\((x,x,pref_{i-1})\),所以说这种情况下\(f_{i,x}=f_{i-1,x}\)

情况2:(\(x\)被更新)

也就是\(x\oplus a_i\),在这种情况下,为了使状态从上一步有效,这三个数中的两个必须相等,第三个必须等于\(pref_{i-1}\)。但是我们又知道\(pref_i\neq pref_{i-1}\),因为\(a_i\neq 0\),也就意味着\(x\)只能等于\(pref_i\)或\(pref_{i-1}\)

\((1)\): \(x=pref_i\),此时的\(f_{i,x}\)依旧等于\(f_{i-1,x}\),因为三元组\((pref_i,pref_i,pref_i)\)可以从\((pref_i,pref_i,pref_{i-1}),(pref_i,pref_{i-1},pref_i),(pref_{i-1},pref_i,pref_i)\)这样的状态转移过来,也就是\(f_{i-1,pref_i}\)

\((2)\): \(x=pref_{i-1}\),这是最复杂的情况,先给出转移:

\[f_{i,pref_{i-1}}=3\cdot f_{i-1,pref_{i-1}}+2\cdot f_{i-1,pref_i}
\]

因为我们对于这样的情况:

\[(pref_{i-1},pref_{i-1},pref_{i-1})
\]

我们有三种方式转移到现在的状态。

而对于这样的情况:

\[(pref_i,pref_{i},pref_{i-1}),(pref_i,pref_{i-1},pref_i),(pref_{i-1},pref_i,pref_i)
\]

我们分别对每个三元组都有两种转移方式。

我们发现,到最后,只有情况\(2(2)\)中的\(f_{i,x}\neq f_{i-1,x}\)。所以出乎意料的,我们只需要计算\(f\)的一个值,并且可以使用滚动数组,甚至不需要倒叙枚举,但是需要注意,由于数组\(a\)中元素很大,我们不能直接开数组,推荐使用散列表,也就是使用STL中的unordered_map容器,最后统计答案的时候,把map里面所存的元素加起来就是最终的答案。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<unordered_map>
#include<vector>
#define ll long long const int MOD = 1e9 + 7;
std::unordered_map<int,ll> dp;
void solve(){
int n;
scanf("%d",&n);
std::vector<int> pref(n + 1);
for(int i = 1;i <= n;++i){
int x;
scanf("%d",&x);
if(i == 1)
{
pref[i] = x;
continue;
}
pref[i] = pref[i - 1] ^ x;
} dp.clear();
dp[0] = 1;
for(int i = 1;i <= n;++i){
dp[pref[i - 1]] = (3 * dp[pref[i - 1]] % MOD + 2 * dp[pref[i]] % MOD) % MOD;
} ll ans = 0;
for(auto it = dp.begin();it != dp.end();++it){
ans = (ans + (*it).second) % MOD;
}
printf("%lld\n",ans);
} int main(){
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}

D1(part div.1)

题意:

到时候自己搜吧,懒得弄过来了,顺便留个心眼,不要在vj上看翻译了。

思路:

dp思路有时间再补了,组合思路反正代码里面有公式,自己理解一下就好了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
const int MOD = 1e9 + 7;
const int MAXN = 1e2 + 10;
const int MAXM = 1e4 + 10; int qpow(int a,int b){
int res = 1;
while(b){
if(b & 1) res = (res * a) % MOD;
a = (a * a) % MOD;
b >>= 1;
}
return res;
} int fac[MAXM],inv[MAXM];
void init(){
fac[0] = 1;
for(int i = 1;i <= 10001;++i) fac[i] = fac[i - 1] * i % MOD;
inv[10001] = qpow(fac[10001],MOD - 2);
for(int i = 10000;i >= 0;--i) inv[i] = inv[i + 1] * (i + 1) % MOD;
} int C(int a,int b){
if(b > a || b < 0 || a < 0) return 0;
return fac[a] * inv[b] % MOD * inv[a - b] % MOD;
} void solve(){
int n,c,m;
std::cin >> n >> c >> m;
for(int i = 1;i <= m;++i){
int x;
std::cin >> x;
} std::cout << C(c * (n - 1),m - c) << '\n';
} signed main(){
int T;
std::cin >> T;
init();
while(T--) solve();
return 0;
}

2025.2.12(CF.R1004.part-div.2)的更多相关文章

  1. CF Round #551 (Div. 2) D

    CF Round #551 (Div. 2) D 链接 https://codeforces.com/contest/1153/problem/D 思路 不考虑赋值和贪心,考虑排名. 设\(dp_i\ ...

  2. CF Round #510 (Div. 2)

    前言:没想到那么快就打了第二场,题目难度比CF Round #509 (Div. 2)这场要难些,不过我依旧菜,这场更是被\(D\)题卡了,最后\(C\)题都来不及敲了..最后才\(A\)了\(3\) ...

  3. 竞赛题解 - CF Round #524 Div.2

    CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...

  4. CF Round #600 (Div 2) 解题报告(A~E)

    CF Round #600 (Div 2) 解题报告(A~E) A:Single Push 采用差分的思想,让\(b-a=c\),然后观察\(c\)序列是不是一个满足要求的序列 #include< ...

  5. cf Round#273 Div.2

    题目链接,点击一下 Round#273 Div.2 ================== problem A Initial Bet ================== 很简单,打了两三场的cf第一 ...

  6. CF Round #509 (Div. 2)

    前言:第一次打\(CF\),因为经验不足以及英语水平很烂,即便在机房大佬的带领下也是花了好久才读懂题目..\(A\)题直到\(11\)分钟才\(A\),题目一共才做了\(4\)题,太菜了.. A. H ...

  7. 【codeforces】【比赛题解】#960 CF Round #474 (Div. 1 + Div. 2, combined)

    终于打了一场CF,不知道为什么我会去打00:05的CF比赛…… 不管怎么样,这次打的很好!拿到了Div. 2选手中的第一名,成功上紫! 以后还要再接再厉! [A]Check the string 题意 ...

  8. 【codeforces】【比赛题解】#937 CF Round #467 (Div. 2)

    没有参加,但是之后几天打了哦,第三场AK的CF比赛. CF大扫荡计划正在稳步进行. [A]Olympiad 题意: 给\(n\)个人颁奖,要满足: 至少有一个人拿奖. 如果得分为\(x\)的有奖,那么 ...

  9. 【codeforces】【比赛题解】#869 CF Round #439 (Div.2)

    良心赛,虽然我迟了半小时233333. 比赛链接:#869. 呃,CF的比赛都是有背景的……上次是<哈利波特>,这次是<物语>…… [A]巧妙的替换 题意: Karen发现了石 ...

  10. 【codeforces】【比赛题解】#868 CF Round #438 (Div.1+Div.2)

    这次是Div.1+Div.2,所以有7题. 因为时间较早,而且正好赶上训练,所以机房开黑做. 然而我们都只做了3题.:(. 链接. [A]声控解锁 题意: Arkady的宠物狗Mu-mu有一只手机.它 ...

随机推荐

  1. Django中图片不显示

    很多教程没教对,导致Django中的图片不能正确的显示出来,经过多次踩坑,发现如下方法可以解决该问题. 1.setting.py中添加: STATIC_URL = '/static/' STATICF ...

  2. 202402 湖北武汉 4D3N3P

    202402 湖北武汉 4D3N3P D0 / 10 杭州出发 普速列车25T Z47 杭州-武昌 城站22:22开 第3候车室 这趟列车是武汉局"华东三直"中的其中一列,另外两列 ...

  3. linux下使用动态壁纸

    让你的linux桌面动起来(幻梦动态壁纸) 我也是突发奇想,做了这么一个程序,目前在多个linux下可以运行,支持双屏 理论上说支持mpv >=29.0 qt>=5.8.0的系统版本 ub ...

  4. WebSocket 与 SSE 对比:即时通信的选择(一)

    在现代 Web 开发中,实时通信需求越来越多,比如聊天应用.实时通知.直播弹幕.股票行情推送等.实现这些需求的常见技术有 WebSocket 和 SSE(Server-Sent Events),但它们 ...

  5. Spring Boot2.5 集成数据库连接池 HikariCP

    目录 §工程环境 §数据库连接池介绍 数据库连接池工作原理剖析 §Java常见数据库连接池性能比较 §数据库连接池选型 Druid vs HikariCP性能对比 §HikariCP为什么这么快 §数 ...

  6. IDEA 调试Java代码的两个技巧

      本文介绍两个使用IDEA 调试Java代码的两个技巧: 修改变量值 使用RuntimeException终止代码执行 修改变量值   在Java代码调试过程中,我们可以修改变量值,使其达到走指定分 ...

  7. 在Mac上使用docker运行gitlab-ce

    首先创建相关路径,并设置权限: mkdir -p /opt/gitlab/{config,data,logs} sudo chmod -R 777 /opt/gitlab 使用如下docker-com ...

  8. 【OSS】存放文件后,网页无法访问,控制台报错无法跨域访问

    来源 BNDong/Cnblogs-Theme-SimpleMemory/issues/403 用自己的oss(阿里云)存了dist,然后按照https://bndong.github.io/Cnbl ...

  9. update注入之我理解

    1.基本语法 update test.test_table set username='admin123',password=000 where id=1; update test.test_tabl ...

  10. pytorch入门 - 修改huggingface大模型配置参数

    介绍 Hugging Face的Transformers库提供了大量预训练模型,但有时我们需要修改这些模型的默认参数来适应特定任务. 本文将详细介绍如何修改BERT模型的最大序列长度(max_posi ...