[32](CSP 集训) CSP-S 模拟 3
A 奇观
考虑到 CCF 可以拆开算,答案为 \((ans_c)^2\times ans_f\)
剩下的东西比较少,考虑 DP
我的 dp 是从爆搜改的,设 \(f_{i,j}\) 表示递归到第 \(i\) 层时 \(j\) 的方案数,原始的爆搜代码如下:
int dfs_f2(int now,int id){
if(now==0) return 1;
if(now==1) return f_c[0][id];
if(f_c[now][id]) return f_c[now][id];//cth<<"dfs "<<now<<" "<<id<<endl;
int res=0;
if(now!=2){
for(int i=1;i<=n;++i){
if(i!=id and hdk.find(i,id)){
res+=dfs_f2(now-1,i);
res%=p;
}
}
}
else{
for(int i=1;i<=n;++i){
if(i!=id and hdk.find(i,id)){
res+=f_c[0][i]*f_c[0][id];
res%=p;
}
}
}
return f_c[now][id]=res%p;
}
可以发现该搜索的最大问题在于内层枚举时的循环,注意到此题是完全图删边形成的,因此考虑做容斥,用总方案数减去不合法的,不合法的可以通过枚举得到
我写的 dp 比较异端,看个乐子就行
scanf("%lld %lld",&n,&m);
for(int i=1;i<=n;++i){
f_c[0][i]=n-1;
}
for(int i=1;i<=m;++i){
int x,y;scanf("%lld %lld",&x,&y);
del_e[x].push_back(y);
del_e[y].push_back(x);
f_c[0][x]--;f_c[0][y]--;
}
int sum=0;
for(int i=1;i<=n;++i){
sum=(sum+f_c[0][i])%p;
}
for(int i=1;i<=n;++i){
f_c[1][i]=fixed(sum-f_c[0][i]);
for(int j:del_e[i]) f_c[1][i]=fixed(f_c[1][i]-f_c[0][j]);
}
sum=0;
for(int i=1;i<=n;++i){
sum=(sum+f_c[1][i])%p;
}
for(int i=1;i<=n;++i){
f_c[2][i]=fixed(sum-f_c[1][i]);
for(int j:del_e[i]) f_c[2][i]=fixed(f_c[2][i]-f_c[1][j]);
}
sum=0;
for(int i=1;i<=n;++i){
sum=(sum+f_c[2][i])%p;
}
int c=sum%p;
memset(f_c[1],0,sizeof f_c[1]);
memset(f_c[2],0,sizeof f_c[2]);
memset(f_c[3],0,sizeof f_c[3]);
sum=0;
for(int i=1;i<=n;++i){
sum=(sum+f_c[0][i])%p;
}
for(int i=1;i<=n;++i){
f_c[1][i]=fixed((sum-f_c[0][i])*f_c[0][i]);
for(int j:del_e[i]){
f_c[1][i]=fixed(f_c[1][i]-f_c[0][j]*f_c[0][i]);
}
}
sum=0;
for(int i=1;i<=n;++i){
sum=(sum+f_c[1][i])%p;
}
for(int i=1;i<=n;++i){
f_c[2][i]=fixed(sum-f_c[1][i]);
for(int j:del_e[i]){
f_c[2][i]=fixed(f_c[2][i]-f_c[1][j]);
}
}
int f=0;
for(int i=1;i<=n;++i){
f=(f+f_c[2][i])%p;
}
cout<<fixed(c*c%p*f)<<endl;
B 铁路
非常好的题
注意到我们没有必要非得去给每次操作新建边,我们可以直接在树上跳 lca 来用并查集合并,这样能解决我们求节点数目的问题:每进行一次操作,节点数加一,并查集上每进行一次合并,节点数减一
然后考虑怎么优化这个过程,注意到,已经在同一个并查集里的数是不需要合并的,因此我们可以借助并查集维护相关信息来直接跳过这段并查集,那么维护什么东西能快速跳节点呢,因为我们是在向根跳,因此我们直接维护并查集中深度最小的节点编号就好了,维护的时候直接往深度最小的节点跳。有人会问这么跳,万一跳过头了怎么办,其实无所谓,因为既然你能跳过头,说明你的目标节点一定在当前并查集内,直接判断当前点和目标点是否在同一并查集内即可
随后我们需要解决新建节点的问题,因为我们并没有真的新建节点,那么如果它询问我们一个新的节点编号,我们要知道往哪里去找。这是很好办的,因为新建节点的下属节点一定已经被合并在同一个并查集里了,因此我们直接维护一个下标,存储每一个新建节点对应的并查集的深度最小的点就行了
#include<bits/stdc++.h>
using namespace std;
#define io_h
// #include"./include/hdk/lib.h"
namespace reader{
template<typename T>
inline void read(T& x){
x=0;bool sym=0;char c=getchar();
while(!isdigit(c)){sym^=(c=='-');c=getchar();}
while(isdigit(c)){x=x*10+c-48;c=getchar();}
if(sym)x=-x;
}
template<size_t N>
inline void read(char (&str)[N]){
size_t n=0;char c=getchar();
while(n<N-1&&!isspace(c)){str[n]=c;c=getchar();++n;}
str[n]=0;
}
template<typename T,typename... Args>
inline void read(T& x,Args&... args){
read(x);read(args...);
}
}
int deep[1000001];
using namespace reader;
template<int size>
struct dsu{
int fa[size+1],minn[size+1];
void clear(int n){
for(int i=1;i<=n;++i){
fa[i]=i;
minn[i]=i;
}
}
int find(int id){
if(id==fa[id]){
return id;
}
fa[id]=find(fa[id]);
return fa[id];
}
void join(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy){
fa[fx]=fy;
if(deep[fx]>deep[fy]){
minn[fx]=minn[fy];
}
}
}
};
int n,m;
int fa[1000001];
dsu<(int)1e6>d;
int ans=0;
int to[1000001];
void join(int x,int y,int newid){
// cout<<"join "<<x<<" "<<y<<endl;
int ori=x;
while(x!=y){
// cout<<"... "<<x<<" "<<y<<"("<<deep[x]<<","<<deep[y]<<")"<<endl;
if(d.find(x)!=x){
// cout<<"find x("<<x<<")!="<<d.find(x)<<endl;
x=d.minn[d.find(x)];
continue;
}
if(d.find(y)!=y){
// cout<<"find y("<<y<<")!="<<d.find(y)<<endl;
y=d.minn[d.find(y)];
continue;
}
if(deep[x]>deep[y]){
d.join(x,fa[x]);
ans--;
x=fa[x];
}
else{
d.join(y,fa[y]);
ans--;
y=fa[y];
}
}
to[newid]=ori;
}
vector<int>e[500001];
void dfs(int now,int last){
fa[now]=last;
deep[now]=deep[last]+1;
for(int i:e[now]){
if(i!=last){
dfs(i,now);
}
}
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
read(n,m);
d.clear(n+m);
for(int i=1;i<=n-1;++i){
int x,y;read(x,y);
e[x].push_back(y);
e[y].push_back(x);
}
dfs(1,0);
for(int i=1;i<=m;++i){
int x,y;read(x,y);
if(x>n) x=to[x];
if(y>n) y=to[y];
join(x,y,n+i);
cout<<n+ans<<endl;
}
}
C.光纤
非常不好的题
旋转卡壳是好的,就是给你一个凸包,让你维护凸包直径,也就是一条直线到凸包内所有节点的最大距离最小
有一个结论,这样的直线一定与凸包的某一条边平行,所以你只需要绕着凸包转一圈就能搞定这个问题
问题是怎么确定凸包上哪个点到这条直线距离最大,有一个显然的 \(n^{2}\) 做法
但实际上不是的,因为这个决策点也有单调性,所以开一个双指针就做完了
这题不好,唐诗有理数类
一开始用的平面向量求点线距做的,后来调不出来了,所以改叉积了
#include<bits/stdc++.h>
using namespace std;
#define int __int128
#define abs(x) (x>=0?x:-x)
void _print(__int128 x,bool first=true){
if(x<0){
putchar('-');
_print(-x,false);
return;
}
if(x==0){
if(first) putchar('0');
return;
}
_print(x/10,false);
putchar((int)(x%10)+'0');
}
namespace reader{
template<typename T>
inline void read(T& x){
x=0;bool sym=0;char c=getchar();
while(!isdigit(c)){sym^=(c=='-');c=getchar();}
while(isdigit(c)){x=x*10+c-48;c=getchar();}
if(sym)x=-x;
}
template<size_t N>
inline void read(char (&str)[N]){
size_t n=0;char c=getchar();
while(n<N-1&&!isspace(c)){str[n]=c;c=getchar();++n;}
str[n]=0;
}
template<typename T,typename... Args>
inline void read(T& x,Args&... args){
read(x);read(args...);
}
}
using namespace reader;
class frac{
private:
int z,m;
public:
frac(int x=0,int y=1){
z=x,m=y;
fixed();
}
frac fixed(){
int gcd=__gcd(abs(z),abs(m));
if(m<0){
m*=-1;z*=-1;
}
if(z==0){
m=1;return *this;
}
if(gcd==0) return *this;
z/=gcd;m/=gcd;
return *this;
}
frac upside(){
return frac(m,z);
}
frac operator = (pair<int,int>A){
z=A.first;m=A.second;fixed();
return *this;
}
frac operator + (frac A){
return (frac(z*A.m+m*A.z,m*A.m)).fixed();
}
frac operator * (frac A){
// cout<<"multi ";this->print();putchar(' ');
// A.print();putchar('=');
int gcd1=__gcd(z,A.m);
int gcd2=__gcd(A.z,m);
frac ans=(frac((z/gcd1)*(A.z/gcd2),(m/gcd2)*(A.m/gcd1))).fixed();
// ans.print();putchar('\n');
return ans;
}
frac operator / (frac A){
return (*this*A.upside()).fixed();
}
frac operator -(){
return frac(-z,m);
}
frac operator -(frac A){
return *this+(-A);
}
bool operator <(frac A){
return z*A.m<A.z*m;
}
bool operator ==(frac A){
return z*A.m==A.z*m;
}
bool operator >(frac A){
return !(*this==A and *this<A);
}
void print(){
fixed();
_print(z);putchar('/');_print(m);
// cout<<z<<"/"<<m<<endl;
}
frac _abs(){
return frac(abs(z),abs(m));
}
long double it(){
return z*1.0/m;
}
};
int n;
int q[1000001],top;
int q1[1000001],top1;
struct node{
__int128 x,y;
}d[1000001],sta[1000001];
#define K(i,j) ((double)(d[j].y-d[i].y)/(d[j].x-d[i].x))
int cha(int x,int y,int z){
return (d[y].x-d[x].x)*(d[z].y-d[x].y)-(d[y].y-d[x].y)*(d[z].x-d[x].x);
}
int len(int x,int y){
return (d[y].x-d[x].x)*(d[y].x-d[x].x)+(d[y].y-d[x].y)*(d[y].y-d[x].y);
}
frac ans;
char anss[1000001];
inline void print(__int128 x){
if(!x)putchar('0');
else{
if(x<0)x=-x,putchar('-');
int cnt=0;
while(x)anss[++cnt]=x%10+'0',x/=10;
for(int i=cnt;i;--i)
putchar(anss[i]);
}
}
signed main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
read(n);
if(n<=2){
ans.print();
return 0;
}
for(int i=1;i<=n;++i){
read(d[i].x,d[i].y);
}
sort(d+1,d+1+n,[](const node&x,const node&y){return x.x==y.x?x.y<y.y:x.x<y.x;});
n=unique(d+1,d+1+n,[](const node&x,const node&y){return x.x==y.x&&x.y==y.y;})-d-1;
for(int i=1;i<=n;++i){
while(top>1 and (K(q[top],i)<=K(q[top-1],q[top]))){
--top;
}
q[++top]=i;
}
for(int i=n;i;--i){
while(top1>1 and K(i,q1[top1])<=K(q1[top1],q1[top1-1]))--top1;
q1[++top1]=i;
}
for(int i=2;i<top1;++i){
q[++top]=q1[i];
}
for(int i=1;i<=top;++i){
sta[i]=d[q[i]];
}
for(int i=1;i<=top;++i){
d[i]=sta[i];
}
int now=1;
for(int i=1;i<=top;++i){
while((now==(i==top?1:i+1))||((abs(cha(now,i,(i==top?1:i+1))))<=(abs(cha((now==top?1:now+1),i,(i==top?1:i+1)))))){
now=(now==top?1:now+1);
}
if(ans==frac(0,1) or ans.it()>(double)cha(now,i,(i==top?1:i+1))*cha(now,i,(i==top?1:i+1))/len(i,(i==top?1:i+1))){
ans=frac(cha(now,i,(i==top?1:i+1))*cha(now,i,(i==top?1:i+1)),len(i,(i==top?1:i+1)));
}
}
(ans*frac(1,4)).print();
}
[32](CSP 集训) CSP-S 模拟 3的更多相关文章
- 20190820 Tue 集训总结&NOIP模拟 27
低谷度过了? 但是skyh阿卡了,还是反衬出我的辣鸡. T1知道要sort,却忘了判重,正解不如暴力分高,555. T2成功化出正解柿子,然后化过头了,化出了无法DP的柿子. 果然不够强,大神们一眼就 ...
- CSP -- 运营商内容劫持(广告)的终结者
缘由 我们公司最近手机端H5 经常受到商户和用户的投诉,说有广告并且导致不能正常进行操作,我们商户自己当然不会加广告了,但是商户和用户可不管这些了,就认为是我们的问题 探索发现根本 目前我们用的很多浏 ...
- 【密码学】CSP的概念
CSP加密服务提供者(Cryptographic Service Provider)具有一下几个特点: CSP是真正执行密码运算的独立模块 物理上一个CSP由两部分组成:一个动态连接库,一个签名文件 ...
- 【转】密码学 :CSP的概念
转:[密码学]CSP的概念 CSP加密服务提供者(Cryptographic Service Provider)具有一下几个特点: CSP是真正执行密码运算的独立模块 物理上一个CSP由两部分组成:一 ...
- CSP初赛复习
初赛复习 初赛一定要过啊,否则付出的那么多都白搭了! while(1) ++csp.rp,++csp.luck,++csp.scores; 历史 2020年开始,除NOIP以外的NOI系列其他赛事(包 ...
- Easyswoole的WaitGroup和Csp组件的分析和使用
Easyswoole的WaitGroup和Csp组件的分析和使用 easyswoole可真是个好名字,只是提供了恰到好处的封装,即使是源码也保持了这样的风格.这种风格不论好坏可能都需要各位适应下,哈哈 ...
- 2020 CSP&NOIP 游记
CSP初赛 CSP初赛 Day -1 早上打了模拟赛,T2寒假正好做过,然而还是还是被踩Orz,郑外NB!.中午出校吃了大盘鸡和拉面,还带回来了三瓶可乐. 初赛知识点看了两页不(看)想(不)看(懂)了 ...
- 前端安全配置之Content-Security-Policy(csp)
什么是CSP CSP全称Content Security Policy ,可以直接翻译为内容安全策略,说白了,就是为了页面内容安全而制定的一系列防护策略. 通过CSP所约束的的规责指定可信的内容来源( ...
- DVWA 黑客攻防实战(十五) 绕过内容安全策略 Content Security Policy (CSP) Bypass
看到标题,是否有点疑惑 CPS 是什么东东.简单介绍一下就是浏览器的安全策略,如果 标签,或者是服务器中返回 HTTP 头中有 Content-Security-Policy 标签 ,浏览器会根据标签 ...
- CSP应用开发-CryptAPI函数库介绍
基本加密函数为开发加密应用程序提供了足够灵活的空间.所有CSP的通讯都是通过这些函数.一个CSP是实现所有加密操作的独立模块.在每一个应用程序中至少需要提供一个CSP来完成所需的加密操作.如果使用多于 ...
随机推荐
- JavaScript一天一个算法题~持续更新中。。。。。
1,数组去重 i.暴力去重 思路:建一个空数组,通过判断原数组的元素是否在空数组内,如果在,不放入,不在,放入空数组. function clearCommnetArray(array){ let a ...
- 如何查询MySQL存储的树形结构,层次结构
表定义如下 如果我们需要在表中查询这个树状结构,通过SQL语句,有两种查询方法: 1.通过inner自连接查询,适用于简单的结构 SELECT * FROM course_category AS on ...
- layui下拉框的数据如何直接从数据库提取(动态赋值)
代码说明部分 第一步:先把layui官方给的模板粘到自己的前端注:下面的代码是我直接从layui官网粘过来的 <div class="layui-form-item"> ...
- 【Maven】概念知识
怎么在Windows安装Maven https://www.cnblogs.com/mindzone/p/12701416.html 学到一个新的指令:查看相对系统变量 echo %XXX_HOME% ...
- 【Java】逗号拼接的取巧处理
需求如图: 这是表的关键处理数据,页面上的输入框要做分开展示,也就是要写业务逻辑来处理 逗号拼接的取巧处理,使用了List集合toString方法来实现,然后移除括号 final String emp ...
- 【转载】联合发布|面向眩晕诊疗的中文医疗对话大模型MedChat发布!
原文地址: https://mp.weixin.qq.com/s/XrddDDpDXHKBcEueH8YXcA ============================================ ...
- 如何在X86_64系统上运行arm架构的docker容器——(异构/不同架构)CPU下的容器启动
近期使用华为的人工智能集群,其中不仅要求异构加速端需要使用昇腾的硬件,更是要求CPU是arm架构的,因此就导致在本地x86电脑上难以对云端的arm版本的镜像进行软件安装和打包操作,为此我们需要在x86 ...
- [POI2015] POD 题解
前言 题目链接:洛谷. 题意简述 长度为 \(n\) 的一串项链,每颗珠子是 \(k\) 种颜色之一.第 \(i\) 颗与第 \(i-1, i+1\) 颗珠子相邻,第 \(n\) 颗与第 \(1\) ...
- CH04_程序流程结构
CH04_程序流程结构 程序流程结构 C/C++支持最基本的三种程序运行结构: 顺序结构:程序按顺序执行,不发生挑战 选择结构:依据条件是否满足,有选择的执行相应的功能 循环结构:依据条件是否满足,循 ...
- 获取微信小程序页面路径
2024/07/12 1.步骤 2.注意事项 3.参考 1.步骤 微信公众号关联小程序时需要用到小程序的页面路径,获取步骤如下:' 登录微信公众平台--工具--生成小程序码--获取更多页面路径--填写 ...