Comet OJ CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)
Preface
在一个月黑风高的夜晚我这个蒟蒻正踌躇着打什么比赛好
是继续做一场AGC,还是去刷一场CF
然后,一道金光闪过(滑稽),我们的红太阳bzt给我指明了方向:
你太菜了,我知道有一场很水的比赛,你快来做吧
然后我就点进比赛,看到了排行榜上Minamoto旁大大的AK二字,不禁心生敬意
同时对于它一人狂得两题一血,身穿两条小裙子的事迹有不免心生敬佩
然后我就开始了刷水之旅(被水题狂虐)
以下题目按照编号顺序排列(怎么感觉在说废话)
A 完全k叉树
一眼发现可以处理出这棵树的深度和最后一层的节点数,然后分类讨论路径的拼法即可
要注意细节,同时还有\(k=1\)的情况要特判
#include<cstdio>
using namespace std;
int t,n,k;
int main()
{
for (scanf("%d",&t);t;--t)
{
scanf("%d%d",&k,&n); int dep=0; long long cur=1,lst=1;
if (k==1) { printf("%d\n",n-1); continue; }
if (n==1) { puts("0"); continue; }
while (cur<n) ++dep,cur=cur+(lst*=k);
cur-=lst; int left=n-cur;
if (left>(lst/k)) printf("%d\n",dep<<1); else printf("%d\n",(dep<<1)-1);
}
return 0;
}
B 距离产生美
比A题简单,发现原序列的数据范围是\(10^5\),\(k\le 10^9\),所以我们要修改就直接改到\(10^{18}\)即可
随便DP一下即可
#include<cstdio>
#include<iostream>
#include<algorithm>
#define RI register int
using namespace std;
const int N=100005;
int n,k,a[N],f[N][2];
int main()
{
RI i; for (scanf("%d%d",&n,&k),i=1;i<=n;++i)
{
scanf("%d",&a[i]); if (abs(a[i]-a[i-1])>=k)
f[i][0]=min(f[i-1][0],f[i-1][1]); else f[i][0]=f[i-1][1];
f[i][1]=min(f[i-1][0],f[i-1][1])+1;
}
return printf("%d",min(f[n][0],f[n][1])),0;
}
C 烤面包片
首先我们肯定容易发现,对于\(x! \operatorname{mod} y\),若\(x>=y\)值一定为\(0\)
然后我们掏出计算器一算就发现\(4!!\)已经大到天上去了(好吧也就\(10^{24}\)级别)
所以我们要考虑的只有\(n=0,1,2,3\)的情况,注意下细节即可(PS:\(0!=1\))
#include<cstdio>
#define RI register int
using namespace std;
int n,mod;
int main()
{
scanf("%d%d",&n,&mod); if (n==0||n==1||n==2) return printf("%d",(n?n:1)%mod),0;
if (n>3) return puts("0"),0; int ret=1;
for (RI i=1;i<=720;++i) ret=1LL*ret*i%mod; return printf("%d",ret),0;
}
D 茶颜悦色
首先我们转化问题,把一个点化为一个矩形,表示若把正方形的某个定点放置在这个矩形内能覆盖到这个点
所以现在问题就变成了平面矩形覆盖次数最多的点,直接扫描线+树状数组即可
#include<cstdio>
#include<iostream>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=400005;
struct line
{
int x,y1,y2,tp;
inline line(CI X=0,CI Y1=0,CI Y2=0,CI Tp=0)
{
x=X; y1=Y1; y2=Y2; tp=Tp;
}
friend inline bool operator < (const line& A,const line& B)
{
return A.x<B.x;
}
}l[N]; int n,k,x,y,rst[N],num,ans;
class Segment_Tree
{
private:
struct segment
{
int mx,tag;
}node[N<<2];
#define M(x) node[x].mx
#define T(x) node[x].tag
#define TN CI now=1,CI l=1,CI r=num
inline void apply(CI now,CI mv)
{
M(now)+=mv; T(now)+=mv;
}
inline void pushup(CI now)
{
M(now)=max(M(now<<1),M(now<<1|1));
}
inline void pushdown(CI now)
{
if (T(now)) apply(now<<1,T(now)),apply(now<<1|1,T(now)),T(now)=0;
}
public:
inline void modify(CI beg,CI end,CI mv,TN)
{
if (beg<=l&&r<=end) return apply(now,mv); int mid=l+r>>1; pushdown(now);
if (beg<=mid) modify(beg,end,mv,now<<1,l,mid);
if (end>mid) modify(beg,end,mv,now<<1|1,mid+1,r); pushup(now);
}
inline int query(void)
{
return M(1);
}
#undef M
#undef T
#undef TN
}SEG;
inline int find(CI x)
{
return lower_bound(rst+1,rst+num+1,x)-rst;
}
int main()
{
RI i,j,k; for (scanf("%d%d",&n,&k),i=1;i<=n;++i)
{
scanf("%d%d",&x,&y); x<<=1; y<<=1; rst[i]=y-k; rst[n+i]=y+k;
l[i]=line(x-k,y-k,y+k,1); l[n+i]=line(x+k+1,y-k,y+k,-1);
}
sort(rst+1,rst+(n<<1)+1); num=unique(rst+1,rst+(n<<1)+1)-rst-1;
for (i=1;i<=(n<<1);++i) l[i].y1=find(l[i].y1),l[i].y2=find(l[i].y2);
for (sort(l+1,l+(n<<1)+1),i=1;i<=(n<<1);i=j+1)
{
for (j=i;j<(n<<1)&&l[j+1].x==l[i].x;++j);
for (k=i;k<=j;++k) SEG.modify(l[k].y1,l[k].y2,l[k].tp);
ans=max(ans,SEG.query());
}
return printf("%d",ans),0;
}
E 飞行棋
有点套路的期望题。首先我们考虑倒推,即用\(f_i\)表示距离终点\(i\)步时的期望步数
显然\(f_0=0\),然后我们考虑对于\(f_i(i\in [1,k])\),它们的答案是什么
发现对于它们任何一个位置,直接走到终点的概率就是\(\frac{1}{k}\),否则就会落入另一个状态
而我们发现这些状态的问题和原问题等价,我们可以很容易地从概率推出它们的期望都是\(k\)
PS:如果你不想观察出这个结论的话你也可以大力列出方程然后高斯消元
然后我们发现接下来的转移由于没有走到终点再走回的这样一个过程,转移就比较单一,即为\(f_i=\frac{1}{k}\cdot \sum_{j=i-k}^{i-1} f_j+1\),我们可以容易的使用矩阵快速幂来优化复杂度到\(O(k^3\cdot\log n)\)
#include<cstdio>
#include<cstring>
#define RI register int
#define CI const int&
using namespace std;
const int N=25,mod=1e9+7;
long long d,k; int invk;
inline void inc(int& x,CI y)
{
if ((x+=y)>=mod) x-=mod;
}
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
struct Matrix
{
int mat[N][N],n,m;
inline Matrix(CI N=0,CI M=0)
{
n=N; m=M; memset(mat,0,sizeof(mat));
}
inline int* operator [] (CI x) { return mat[x]; }
friend inline Matrix operator * (Matrix A,Matrix B)
{
Matrix C(A.n,B.m); for (RI i=0;i<C.n;++i)
for (RI j=0;j<C.m;++j) for (RI k=0;k<A.m;++k)
inc(C[i][j],1LL*A[i][k]*B[k][j]%mod); return C;
}
friend inline Matrix operator ^ (Matrix A,long long p)
{
Matrix T(A.n,A.m); for (RI i=0;i<A.n;++i) T[i][i]=1;
for (;p;p>>=1,A=A*A) if (p&1) T=T*A; return T;
}
};
int main()
{
scanf("%lld%lld",&d,&k); Matrix S(k+1,1),P(k+1,k+1);
RI i; for (invk=quick_pow(k%mod),i=0;i<k;++i) S[i][0]=k; S[k][0]=1;
for (i=0;i<k-1;++i) P[i][i+1]=1; for (i=0;i<k;++i) P[k-1][i]=invk;
P[k-1][k]=P[k][k]=1; P=P^(d-k); S=P*S; return printf("%d",S[k-1][0]),0;
}
F 三元组
我们考虑把\(\min,\max\)去掉,那么我们强制\(a_i+a_j\)是\(\min\),这样题目就变成求\(2\cdot(a_i+a_j)\le b_i+b_j\)的\(c_i\cdot c_j\)的和
把式子拆开并移项就得到了\((2\cdot a_i-b_i)+(2\cdot a_j-b_j)\le 0\),这个我们记\(2\cdot a_i-b_i\)为\(d_i\),然后把\(d_i\)排序后two points扫一下用前(后)缀和算答案即可
若\(b_i+b_j\)是\(\min\)的话就交换所有\(a_i,b_i\)再做一次即可
#include<cstdio>
#include<algorithm>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005,mod=1e9+7;
struct data
{
int a,b,c,v;
friend inline bool operator < (const data& A,const data& B)
{
return A.v<B.v;
}
}p[N]; int n,suf[N],ans;
inline void inc(int& x,CI y)
{
if ((x+=y)>=mod) x-=mod;
}
inline int calc(int ret=0)
{
RI i,j; for (i=1;i<=n;++i) p[i].v=p[i].b-2*p[i].a;
for (sort(p+1,p+n+1),i=n;i;--i) suf[i]=suf[i+1],inc(suf[i],p[i].c);
for (i=n,j=1;i;--i)
{
while (j<=n&&p[i].v+p[j].v<0) ++j;
if (j<=n) inc(ret,1LL*p[i].c*suf[max(i,j)]%mod);
}
return ret;
}
int main()
{
RI i; for (scanf("%d",&n),i=1;i<=n;++i)
scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c);
for (ans=calc(),i=1;i<=n;++i) swap(p[i].a,p[i].b);
return inc(ans,calc()),printf("%d",ans),0;
}
G 篮球校赛
律师函警告(不是)
首先我们很容易发现我们对于\(5\)个位置每个位置挑出前\(5\)的队员然后最优解一定在它们之中(否则要它有什么用?)
然后还愣着干什么,直接\(O(5^5)\)甚至\(O(2^{25})\)大暴力就过了啊
#include<cstdio>
#include<iostream>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
struct data
{
int val,id,tp;
friend inline bool operator < (const data& A,const data& B)
{
return A.val>B.val;
}
}a[5][N],t[30]; int n,cnt; long long ans; bool cs[N];
inline void DFS(CI nw=1,CI ct=0,CI st=0,const long long& sum=0)
{
if (nw>cnt) { if (ct==5) ans=max(ans,sum); return; }
if (!cs[t[nw].id]&&!((st>>t[nw].tp)&1))
cs[t[nw].id]=1,DFS(nw+1,ct+1,st|(1<<t[nw].tp),sum+t[nw].val),cs[t[nw].id]=0; DFS(nw+1,ct,st,sum);
}
int main()
{
RI i,j; for (scanf("%d",&n),i=1;i<=n;++i)
for (j=0;j<5;++j) scanf("%d",&a[j][i].val),a[j][i].id=i,a[j][i].tp=j;
for (i=0;i<5;++i) for (sort(a[i]+1,a[i]+n+1),j=1;j<=5;++j) t[++cnt]=a[i][j];
return DFS(),printf("%lld",ans),0;
}
H 分配学号
首先容易发现最后修改的学号序列在排序后是唯一的,只不过有些人可以被改动到的数字不一样
我们考虑先扫一遍求出目标序列,然后将原序列和目标序列都排序,然后two points维护下每个数能从多少个数变过来,然后乘起来就好了
#include<cstdio>
#include<algorithm>
#define RI register int
using namespace std;
const int N=100005,mod=1e9+7;
int n,ans=1; long long a[N],tar[N];
int main()
{
RI i,j; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%lld",&a[i]);
for (sort(a+1,a+n+1),i=1;i<=n;++i)
if (a[i]<=tar[i-1]) tar[i]=tar[i-1]+1; else tar[i]=a[i];
for (sort(tar+1,tar+n+1),i=j=1;i<=n;++i)
{
while (j<=n&&a[j]<=tar[i]) ++j;
ans=1LL*ans*(j-i)%mod;
}
return printf("%d",ans),0;
}
I Gree的心房
整场比赛最水的题,容易发现最少步数一定是\(n+m-2\),所以判断\(k\)和它的关系即可
注意起点和终点不能被占用了以及计算剩下多少个无用位置时要开long long
#include<cstdio>
using namespace std;
int n,m,k;
int main()
{
scanf("%d%d%d",&n,&m,&k); long long left=1LL*n*m-(n+m-1);
if (k>left) puts("-1"); else printf("%d",n+m-2); return 0;
}
Postscript
当我做完这场比赛,看着自己每道题都WA上三四遍的提交,再看着现场AK并拿两题一血的bzt,我流下了蒟蒻的泪水
Comet OJ CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)的更多相关文章
- [CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)]飞行棋
题目链接:https://www.cometoj.com/contest/59/problem/E?problem_id=2714 求期望并且一堆转移基本上就是期望dp了(叉腰 照常的设dp[i]表示 ...
- Comet OJ 夏季欢乐赛 篮球校赛
Comet OJ 夏季欢乐赛 篮球校赛 题目传送门 题目描述 JWJU注重培养学生的"唱,跳,rap,篮球"能力.于是每年JWJU都会举办篮球校赛,来给同学们一个切磋篮球技术的平台 ...
- Comet OJ 夏季欢乐赛 Gree的心房
Comet OJ 夏季欢乐赛 Gree的心房 题目传送门 题目描述 据说每一个走进Gree哥哥心房的小姑娘都没有能够再走出来-- 我们将Gree哥哥的心房抽象成一个n \times mn×m的地图,初 ...
- Comet OJ 夏季欢乐赛 分配学号
Comet OJ 夏季欢乐赛 H 分配学号 题目传送门 题目描述 今天,是JWJU给同学们分配学号的一天!为了让大家尽可能的得到自己想要的学号,鸡尾酒让大家先从 [1,10^{18}][1,1018] ...
- Comet OJ 2019 夏季欢乐赛题解
Comet OJ 2019 夏季欢乐赛题解 我是来骗访问量的 A 完全k叉树 \(n\)个点的完全k叉树的直径. 直接做 B 距离产生美 直接做 C 烤面包片 \(n!!!\mod p\) 显然\(n ...
- CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)D
题面 一开始想到一个 O(N^2) 做法,先把x排序,然后顺次枚举x最大的点,看向前最多可以保留多少点 (也就是先不管正方形的上下长度限制,先考虑左右的限制).然后再对这些点做一遍类似的..(等等这么 ...
- CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)F
题面 F比较友善(相较于E),我们发现如果i和j是满足条件的两个下标,那么: a[i]-2*b[i] + a[j]-2*b[j] >=0 或者 b[i]-2*a[i] + b[j]-2*a[j] ...
- CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)E
题面 这个题暴好啊,考了很多东西. 首先设f(x)为离终点还有x步要走的期望步数,我们可以发现 : 1.x>=k时,x可以转移到的点的下标都<x. 2.x<k时,则可能走回到x或者下 ...
- CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)H
题面 被神葱安利安利了本题. 我们贪心的想,如果有那么一坨相等的学号,那么肯定是保留一个人学号不变,其余的再推到学号+1的位置(准备与那个位置的其他人合并)处理. 虽然a[i]可大至1e18,不过如果 ...
随机推荐
- python接口自动化9-ddt数据驱动
前言 ddt:数据驱动,说的简单一点,就是多组测试数据,比如点点点的时候登录输入正常.异常的数据进行登录. 实际项目中,自动化测试用得很少,但也有人用excel来维护测试数据 一.ddt 1.安装:p ...
- 『嗨威说』算法设计与分析 - 回溯法思想小结(USACO-cha1-sec1.5 Checker Challenge 八皇后升级版)
本文索引目录: 一.回溯算法的基本思想以及个人理解 二.“子集和”问题的解空间结构和约束函数 三.一道经典回溯法题点拨升华回溯法思想 四.结对编程情况 一.回溯算法的基本思想以及个人理解: 1.1 基 ...
- linux服务器上配置进行kaggle比赛的深度学习tensorflow keras环境详细教程
本文首发于个人博客https://kezunlin.me/post/6b505d27/,欢迎阅读最新内容! full guide tutorial to install and configure d ...
- oracle中decode函数用法及应用
用法 1.decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 相当于if else 那种方式. 2.decode(字段或字段的运算,值1,值2,值3) 当字段或字段的运 ...
- jquery 图片缩放插件使用
https://cdn.bootcss.com/d3-transition/1.1.1/d3-transition.js http://www.jq22.com/jquery-info9291
- python中反转列表的三种方式
1.内建函数reversed() li =[1, 2, 3, 4, 5, 6] a = list(reversed(li)) print (a) 注意:reversed()函数返回的是一个迭代器,而不 ...
- MySQL,必须掌握的6个知识点
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- C# abstract 和 interface 区别
抽象类主要用来提供多个派生类可共享的基类的公共定义,它与非抽象类的主要区别如下: 抽象类不能直接实例化. 抽象类中可能包含抽象成员,但非抽象类中不可以. 抽象类不能被密封. 接口具有以下特征 接口类类 ...
- uni-app自定义Modal弹窗组件|仿ios、微信弹窗效果
介绍 uniapp自定义弹窗组件uniPop,基于uni-app开发的自定义模态弹窗|msg信息框|alert对话框|confirm确认框|toast弱提示框 支持多种动画效果.多弹窗类型ios/an ...
- arcgis api for javascript 学习(四) 地图的基本操作
1.文章讲解的为地图的平移.放大.缩小.前视图.后视图以及全景视图的基本功能操作 2.主要用到的是arcgis api for javascript中Navigation的用法,代码如下: <! ...