题解-Codeforces1106全套
因为参加完wc后心情很差,而且在广州过年没Ubuntu,所以就没打这场比赛了,结果这套题全部1A了,现在看来真是错失良机 结果这场不计rating
今天是除夕,大家节日快乐
A. Lunar New Year and Cross Counting
题意
给定 \(n\times n\) 的 \(01\) 矩阵,定义一个十字为摆成X
的五个 \(1\) ,问矩阵内部有多少这种十字(\(n\leq 500\))
思路
A题不出意外一般是直接模拟,复杂度\(O(n^2)\)
代码
#include <bits/stdc++.h>
using namespace std;
const char ch='X';
char s[503][503];
int n,ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%s",s[i]+1);
for(int i=2;i<n;++i)
for(int j=2;j<n;++j)
if(s[i][j]==ch && s[i-1][j-1]==ch && s[i-1][j+1]==ch && s[i+1][j-1]==ch && s[i+1][j+1]==ch)
++ans;
cout << ans << endl;
return 0;
}
B. Lunar New Year and Food Ordering
题意
给定\(n\)份食物,每份食物有自己的价格和数量,给定\(m\)个依次到达的客人,第\(i\)个人会要\(d_i\)个第\(t_i\)种食物,若不够,则从剩下食物中最便宜的选起,求每人的花费(\(n,m\leq 10^5\))
思路
感觉随便乱搞的题,关键在于如何快速找到剩下食物中最便宜的,只要将食物按价格升序排序后记录一个指针即可,在该指针前的食物全部售罄,复杂度\(O(n\log n+m)\)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename _tp> inline void read(_tp&x){
char c11=getchar(),ob=0;x=0;
while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;
}
const int N=101003;
int c[N],v[N],t[N];
int n,m;
inline bool cmp(const int&A,const int&B){return v[A]<v[B];}
int main(){
read(n),read(m);
for(int i=1;i<=n;++i)read(c[i]);
for(int i=1;i<=n;++i)read(v[i]);
for(int i=1;i<=n;++i)t[i]=i;
sort(t+1,t+n+1,cmp);
int lst=1,ps,ct;
ll ans;
while(m--){
read(ps),read(ct);
if(c[ps]>=ct)c[ps]-=ct,ans=(ll)ct*v[ps];
else {
ans=(ll)c[ps]*v[ps];
ct-=c[ps],c[ps]=0;
while(lst<=n){
int id=t[lst];
if(c[id]>=ct){
c[id]-=ct;
ans+=(ll)ct*v[id];
ct=0;
break;
}ct-=c[id];
ans+=(ll)c[id]*v[id];
c[id]=0;
++lst;
}
if(ct)ans=0;
}
printf("%I64d\n",ans);
}
return 0;
}
C. Lunar New Year and Number Division
题意
给定\(n\)个元素(保证\(n\)为偶数),将这些元素划分为若干个组,要求每个组元素个数不低于两个,不设上限,每个组的权值为组内元素和的平方,定义一种划分方案的权值为所有组贡献的和,求划分方案的最小值(\(n\leq 3\times 10^5\))
思路
题目给了很好的提示,应该能猜想一定存在一种最优划分将元素划分为两两一组,想法证明:
首先若存在一组超过四个元素的,定能将其划分为若干个更小的组,相应的,其贡献也会更低
若存在一组三个元素的,由于\(n\)为偶数,则定能找到另一组三个元素,由于三个元素\(a,b,c\)的贡献为\(a^2+b^2+c^2+2ab+2ac+2bc\),由于其中平方项是无论如何划分都会产生的,所以有区别的只有\(2ab+2ac+2bc\),产生了三个附加项,两个组共六个附加项,若划分为两两一组,则只会产生三个附加项,再加分类讨论即可证明两两一组更优
现在知道了两两一组最优,但如何划分?由于要尽量避免两个大元素相乘,所以第\(i\)小元素和第\(i\)大元素一组。想法证明:
对四个元素的情况进行讨论:
设 \(a\leq b\leq c\leq d\),要证\(ad,bc\)一组最优
即证\(\begin{cases}
ab+cd-ad-bc\geq 0\\
ac+bd-ad-bc\geq 0
\end {cases}\)对于上面的式子:
\[ab+cd-ad-bc=(d-b)(c-a)\geq 0
\]对于下面的式子:
\[ac+bd-ad-bc=(d-c)(b-a)\geq 0
\]即可证明四个元素情况下\(ad\)一组,\(bc\)一组最优,将四个元素的情况进行拓展即可
时间复杂度\(O(n\log n)\)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename _tp> inline void read(_tp&x){
char c11=getchar(),ob=0;x=0;
while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;
}
int a[301003],n;
int main(){
read(n);
for(int i=n;i;--i)read(a[i]);
sort(a+1,a+n+1);
ll ans = 0ll;
for(int i=n>>1;i;--i)
ans += (a[i]+a[n-i+1]) * (a[i]+a[n-i+1]);
cout << ans << endl;
return 0;
}
D. Lunar New Year and a Wander
题意
给定\(n\)点\(m\)边无向图,从任意点出发,每次可以到达一个已达点(不一定是当前点)的相邻点,得到一个到达所有点的顺序(一个排列),问该顺序的最小字典序(\(n,m\leq 10^5\))
思路
和NOIp2018Day2T1有点像(不是同一道题啦( ̄▽ ̄))
这题只要将相邻点加入堆,每次从堆里头选即可(要判是否已达)
时间复杂度\(O(n\log n+m)\)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename _tp> inline void read(_tp&x){
char c11=getchar(),ob=0;x=0;
while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;
}
const int N=101003;
struct Edge{int v,nxt;}a[N+N];
int head[N],vis[N],ans[N];
int n,m,_;
priority_queue <int> h;
inline void ad(){
static int x,y;read(x),read(y);
a[++_].v=y,a[_].nxt=head[x],head[x]=_;
a[++_].v=x,a[_].nxt=head[y],head[y]=_;
}
int main(){
read(n),read(m);
while(m--)ad();
h.push(-1);vis[1]=1;
while(!h.empty()){
int x=-h.top();h.pop();
ans[++ans[0]]=x;
for(int&i=head[x];i;i=a[i].nxt)
if(!vis[a[i].v])h.push(-a[i].v),vis[a[i].v]=1;
}
for(int i=1;i<=n;++i)printf("%d ",ans[i]);
return 0;
}
E. Lunar New Year and Red Envelopes
题意
在一段长为\(n\)的时间内,Bob有\(k\)个红包可领取,第\(i\)个红包只能在时间\([l_i,r_i]\)间领取,价值\(w_i\),选择后在时刻\(d_i\)前都不能再选其他红包
Bob有自己的选红包策略,若某时刻Bob可以选取红包:
- 选择当前可选红包中最大的
- 若有多个红包最大,则选择\(d\)最大的
所以Bob的收益其实是固定的。但Alice会来捣乱,她有\(m\)次机会扰乱Bob,每次可以使得Bob在一个时间点不选红包,问Bob的最小收益(Bob的策略恒定不变)
(\(n\leq 10^5,m\leq 200,k\leq 10^5\))
思路
看到\(m\)这么小首先考虑Dp
设\(f[i][j]\)表示前 \(i\) 的时间内使用了 \(j\) 次扰动的最小收益,首先尝试用\(f[i][j]\)去更新\(f[i+1][j+1]\)
然后考虑若 \(i\) 时刻可以选红包,则选择的红包是固定的,若红包对应的\(d\)为\(D\),收益\(W\),则可以用\(f[i][j]+W\)去尝试更新\(f[D+1][j]\)
若 \(i\) 时刻不能选红包,则可以用\(f[i][j]\)去尝试更新\(f[i+1][j]\)
时刻 \(i\) 选择的红包可以用堆或线段树预处理
时间复杂度\(O(nm+k\log k)\)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename _tp> inline void read(_tp&x){
char c11=getchar(),ob=0;x=0;
while(c11!='-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;
}
inline void cmin(ll&A,ll B){if(A>B)A=B;}
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int N=101003;
int d[N],w[N];
ll f[N][203];
int n,m,k,tp;
struct node{
int l,r,d,w;
inline void in(){read(l),read(r),read(d),read(w);}
friend inline bool operator < (const node&A,const node&B) {return A.w!=B.w?A.w<B.w:A.d<B.d;}
friend inline bool operator > (const node&A,const node&B) {return A.w!=B.w?A.w>B.w:A.d>B.d;}
}p[N],h[N];
inline bool cmp (const node&A,const node&B) {return A.l<B.l;}
inline void push(node x){
h[++tp]=x;
int pp=tp;
while(pp>1 and h[pp]>h[pp>>1])
swap(h[pp],h[pp>>1]),pp>>=1;
}
inline void pop(){
h[1]=h[tp--];int pp=1;
while(((pp<<1)<=tp and h[pp]<h[pp<<1]) or ((pp<<1|1)<=tp and h[pp]<h[pp<<1|1])){
pp<<=1;
if(h[pp]<h[pp|1])pp|=1;
swap(h[pp],h[pp>>1]);
}
}
int main(){
read(n),read(m),read(k);
for(int i=1;i<=k;++i)p[i].in();
sort(p+1,p+k+1,cmp);
for(int i=1,id=1;i<=n;++i){
while(id<=k and p[id].l<=i)push(p[id]),++id;
while(tp and h[1].r<i)pop();
if(tp)d[i]=h[1].d,w[i]=h[1].w;
else d[i]=i;
}
for(int i=n+1;~i;--i)
for(int j=m;~j;--j)
f[i][j] = inf;
f[0][0]=0;
for(int i=0;i<=n;++i)
for(int j=0;j<=m;++j){
cmin(f[i+1][j+1],f[i][j]);
cmin(f[d[i]+1][j],f[i][j]+w[i]);
}
ll ans = inf;
for(int j=0;j<=m;++j)
cmin(ans,f[n+1][j]);
printf("%I64d\n",ans);
return 0;
}
F. Lunar New Year and a Recursive Sequence
题意
已知一个序列的前\(k-1\)项为\(1\),第\(n\)项为\(m\),和其递推式:\(f_i=\prod_{j=1}^kf_{i-j}^{b_i}\)
求该序列第 \(k\) 项
(\(k\leq 100,k<n\leq 10^9\),题目在模\(998244353\)条件下进行)
思路
比较无趣的一题
首先递推式使用幂次积而非乘积和则考虑对指数进行递推,非常幸运地发现\(f_i=1=f_k^0(i<k)\),所以可以矩乘快速幂求解\(f_n\)是\(f_k\)的多少次方
现在的瓶颈在于求\(x^t\equiv b(\bmod p)\),也就是求……k次剩余?
想法将幂次再次化简,想到模数有原根\(g=3\),设
\(\begin{cases}
b\equiv g^{b_0}\pmod p\\
x\equiv g^{x_0}\pmod p
\end{cases}\)
将原式化简为\(g^{x_0t}\equiv g^{b_0}\pmod p\)
即\(x_0\cdot t\equiv b_0\pmod {(p-1)}\)
裸bsgs可得\(g_0\),利用该式可裸exgcd求解\(x_0\)
最后答案为\(f_k=x\equiv g^{x_0}\pmod p\)
记得所有对幂次进行取模都要对\(p-1\)取模!!!
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=103,p=998244353;
struct mat{
int n,m,a[N][N];
inline mat(){memset(a,0,sizeof a);}
inline mat(const int&nn,const int&mm):n(nn),m(mm){for(int i=0;i<n;++i)for(int j=0;j<m;++j)a[i][j]=0;}
friend inline mat operator * (const mat&A,const mat&B) {
mat res(A.n,B.m);
for(int i=0;i<A.n;++i)
for(int k=0;k<A.m;++k)if(A.a[i][k])
for(int j=0;j<B.m;++j)
res.a[i][j]=(res.a[i][j]+(ll)A.a[i][k]*B.a[k][j])%(p-1);
return res;
}
};
int exgcd(int a,int b,int&x,int&y){
if(!b){x=1,y=0;return a;}
int t=exgcd(b,a%b,y,x);
y-=a/b*x;return t;
}
inline int qpow(int A,int B){
int res(1);while(B){
if(B&1)res=(ll)res*A%p;
A=(ll)A*A%p,B>>=1;
}return res;
}
map <int,int> mp;
int bsgs(int x){
int sr=40000;
int bs=1;
for(int i=0;i<=sr+10;++i)
mp[bs]=i,bs=3ll*bs%p;
int inv=qpow(qpow(3,sr),p-2);
for(int i=0;;++i){
if(mp.find(x)!=mp.end())
return i*sr+mp[x];
x=(ll)x*inv%p;
}
}
int main(){
int k,n,m;
scanf("%d",&k);
mat A(k,k);
for(int i=0;i<k-1;++i)
A.a[i][i+1]=1;
for(int i=k-1;~i;--i)
scanf("%d",&A.a[k-1][i]);
scanf("%d%d",&n,&m);
mat res(k,1);
res.a[k-1][0]=1;
int B=n-k;
while(B){
if(B&1)res=A*res;
A=A*A,B>>=1;
}
int t=res.a[k-1][0],x,y;
int gcd=exgcd(t,p-1,x,y),gm=bsgs(m);
if(gm%gcd){puts("-1");return 0;}
x=(x+p-1)%(p-1);
x=(ll)x*(gm/gcd)%(p-1);
printf("%d\n",qpow(3,x));
return 0;
}
题解-Codeforces1106全套的更多相关文章
- 题解-HAOI2018全套
去冬令营转了一圈发现自己比别人差根源在于刷题少,见过的套路少(>ω<) 于是闲来无事把历年省选题做了一些 链接放的都是洛谷的,bz偷懒放的也是链接 AM.T1 奇怪的背包 Problem ...
- 【qboi冲刺NOIP2017复赛试题4】 全套题目+题解+程序
作为一个好人(验题人),我给大家奉上下这套题的题解,并且预祝大家这套题能够AK: T1题面:Alice现在有n根木棍,他们长度为1,2,3....n,Bob想把某一些木棍去掉,使得Alice剩下的木棍 ...
- POJ1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释
http://poj.org/problem?id=1389 题面描述在二维xy平面中有N,1 <= N <= 1,000个矩形.矩形的四边是水平或垂直线段.矩形由左下角和右上角的点定义. ...
- CCPC、Petrozavodsk Camp、OpenCup 题解汇总
省赛 \([\text{2021.11.30}]\) 2021 Jilin Collegiate Programming Contest 全部完成. \([\text{2021.12.25}]\) 2 ...
- 马哥linux运维初级+中级+高级 视频教程 教学视频 全套下载(近50G)
马哥linux运维初级+中级+高级 视频教程 教学视频 全套下载(近50G)目录详情:18_02_ssl协议.openssl及创建私有CA18_03_OpenSSH服务及其相关应用09_01_磁盘及文 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
随机推荐
- 网络虚拟化基础一:linux名称空间Namespaces
一 介绍 如果把linux操作系统比作一个大房子,那命名空间指的就是这个房子中的一个个房间,住在每个房间里的人都自以为独享了整个房子的资源,但其实大家仅仅只是在共享的基础之上互相隔离,共享指的是共享全 ...
- Please check that your locale settings问题
问题描述: perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: L ...
- 基于Metronic的Bootstrap开发框架--工作流模块功能介绍
在很早之前的随笔里面,已经介绍了WInform框架中工作流模块的功能,不过由于工作流模块中界面处理部分比较麻烦,一直没有在Bootstrap框架中进行集成,最近由于项目的关系,花了不少精力,把工作流模 ...
- IS创新之路 -- 都昌公司赋能型HIT企业发展之路
◆◆前言 近日,上海瑞金医院对我司表示:“我院从2000年开始自主开发医院信息系统,走出了一条可持续的信息化发展之路.已建成五大系统,284个子系统.但我院仍然坚持在努力推进以电子病历为核心医院信息化 ...
- 控制结构(8): 线性化(linearization)
// 上一篇:管道(pipeline) // 下一篇:程序计数器(PC) "编程语言不过是一个工具,什么语言都一样","编程语言能改变人的思维,不同的语言会带给你不同的思 ...
- vuex学习总结
vuex 学习 mapState,mapGetters 一般也写在 computed 中 , mapActions 一般写在 methods中.
- react性能优化
前面的话 本文将详细介绍react性能优化 避免重复渲染 当一个组件的props或者state改变时,React通过比较新返回的元素和之前渲染的元素来决定是否有必要更新实际的DOM.当他们不相等时,R ...
- js对内容进行编码(富文本编辑器使用居多)
escape(string)函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串. 使用unescape(string) 对 escape() 编码的字符串进行解码.
- Node.js修改全局安装默认路径
因为苦于C盘不够的烦恼,不想把全局安装包的路径弄在C盘,于是有了这篇文章: 查看设置 npm config ls //查看设定信息,,找到prefix一行,默认是一般是在C盘 修改命令如下 npm c ...
- BZOJ 1671: [Usaco2005 Dec]Knights of Ni 骑士 (bfs)
题目: https://www.lydsy.com/JudgeOnline/problem.php?id=1671 题解: 按题意分别从贝茜和骑士bfs然后meet_in_middle.. 把一个逗号 ...