Codeforces 1065 简要题解
传送门
GGG题略难,膜了一波zhouyuyang{\color{red} zhouyuyang}zhouyuyang巨佬的代码。
其余都挺清真的。
A题
传送门
题意:你有sss元钱,现在每颗糖ccc元,每买aaa颗会送你bbb颗,问最多买几颗糖。
思路:按照题意模拟。
代码:
#include<bits/stdc++.h>
#define ri register int
#define int long long
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef long long ll;
signed main(){
for(ri s,a,b,c,tt=read();tt;--tt){
s=read(),a=read(),b=read(),c=read();
cout<<(ll)s/c/a*(a+b)+((s-s/c/a*c*a)/c)<<'\n';
}
return 0;
}
B题
传送门
题意:给你nnn个点mmm条边让你随意构造无向图,称度为000的点为孤立点,问孤立点数量的最小值和最大值。
思路:
要使得数量最小显然每两个点连一条边,数量最大的话显然尽量拿去建完全图,随便判一判就完了。
注意m读入可能会爆int!!!233333333333
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
typedef long long ll;
inline ll read(){
ll ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
signed main(){
ll n=read(),m=read();
cout<<max(0ll,n-m*2)<<' ';
for(ll i=0;;++i){
if(i*(i-1)/2<m)continue;
cout<<n-i;
break;
}
return 0;
}
C题
传送门
题意:给你一排积木,没个积木有高度hih_ihi。
让你每次指定一个高度把所有高于它的部分都砍掉,每次砍的代价是砍掉的所有高度之和,问如果每次砍的代价都不能超过给定的kkk最少砍几次。
思路:考虑时间倒流,改为每次加一部分,预处理前缀和+二分求每次可以走的最上点即可。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
typedef long long ll;
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef long long ll;
const int N=2e5+5;
int n,k,a[N],mn=0x3f3f3f3f,mx=-0x3f3f3f3f;
ll cnt[N],det[N];
signed main(){
n=read(),k=read();
for(ri i=1;i<=n;++i)a[i]=read();
sort(a+1,a+n+1);
for(ri i=1;i<=n;++i){
++det[a[1]],--det[a[i]+1];
}
mn=a[1],mx=a[n];
for(ri i=mn;i<=mx;++i)cnt[i]=cnt[i-1]+det[i];
for(ri i=mn+1;i<=mx;++i)cnt[i]+=cnt[i-1];
int turn=0;
while(mn!=mx){
++turn;
int l=mn+1,r=mx,res=mn+1;
while(l<=r){
int mid=l+r>>1;
if(cnt[mid]-cnt[mn]<=k)l=mid+1,res=mid;
else r=mid-1;
}
mn=res;
}
cout<<turn;
return 0;
}
D题
传送门
题意:给你一个n∗nn*nn∗n的国际象棋,每个格子上有一个111~n2n^2n2之间的正整数,每个格子上的数互不相同。你有三个棋子象,车和马,每次可以选择切换一种棋子或者走一步,问从111所在格子走到222所在格子再走到333所在格子这样下去一直走到n2n^2n2所在格子所需的最短步数,以及在所有最短的方案中最小的换棋子的次数。
思路:直接暴力建边跑n2n^2n2次最短路即可。
注意车和象可以分别对行,列,主对角线,副对角线建虚点优化边数。
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef pair<int,int> pii;
const int N=15,inf=0x3f3f3f3f;
int a[15][15],h[N],l[N],x[N<<1],y[N<<1],n,val[1005],tot;
struct Node{int v,w,col;};
vector<Node>e[1005];
inline void add(int u,int v,int w,int col){e[u].push_back((Node){v,w,col});}
map<pii,bool>in;
map<pii,pii>pred;
inline void solve(){
static int hd,tl,s,t;
static pii q[1005],dis[1005][4];
dis[1][1]=pii(0,0),dis[1][2]=pii(0,0),dis[1][3]=pii(0,0);
for(ri tt=1;tt<n*n;++tt){
s=tt,t=tt+1;
for(ri i=1;i<=tot;++i){
if(i==s)continue;
for(ri j=1;j<=3;++j)dis[i][j]=pii(inf,inf);
}
hd=1,tl=0;
in[q[++tl]=pii(s,1)]=1,in[q[++tl]=pii(s,2)]=1,in[q[++tl]=pii(s,3)]=1;
pred.clear();
while(hd<=tl){
pii x=q[hd++];
in[x]=0;
for(ri i=0,v,w,col;i<e[x.fi].size();++i){
v=e[x.fi][i].v,w=e[x.fi][i].w,col=e[x.fi][i].col;
pii tmp=pii(dis[x.fi][x.se].fi+w+val[v]+(x.se!=col),dis[x.fi][x.se].se+(x.se!=col));
if(tmp<dis[v][col]){
dis[v][col]=tmp;
pred[pii(v,col)]=x;
if(!in[pii(v,col)])in[q[++tl]=pii(v,col)]=1;
}
}
}
}
pii res=min(min(dis[t][1],dis[t][2]),dis[t][3]);
cout<<res.fi<<' '<<res.se<<'\n';
}
int main(){
n=read();
for(ri i=1;i<=n;++i)for(ri j=1;j<=n;++j)a[i][j]=read();
for(ri i=1;i<=n;++i)for(ri j=1;j<=n;++j){
if(i>1&&j>2)add(a[i][j],a[i-1][j-2],1,1);
if(i>1&&j<n-1)add(a[i][j],a[i-1][j+2],1,1);
if(i>2&&j>1)add(a[i][j],a[i-2][j-1],1,1);
if(i>2&&j<n)add(a[i][j],a[i-2][j+1],1,1);
if(i<n&&j>2)add(a[i][j],a[i+1][j-2],1,1);
if(i<n&&j<n-1)add(a[i][j],a[i+1][j+2],1,1);
if(i<n-1&&j>1)add(a[i][j],a[i+2][j-1],1,1);
if(i<n-1&&j<n)add(a[i][j],a[i+2][j+1],1,1);
}
tot=n*n;
for(ri i=1;i<=n;++i){
val[h[i]=++tot]=1;
for(ri j=1;j<=n;++j)add(a[i][j],h[i],0,2),add(h[i],a[i][j],0,2);
}
for(ri i=1;i<=n;++i){
val[l[i]=++tot]=1;
for(ri j=1;j<=n;++j)add(a[j][i],l[i],0,2),add(l[i],a[j][i],0,2);
}
for(ri det,i=1;i<=n*2-1;++i){
val[x[i]=++tot]=1,det=i-n;
for(ri j=1;j<=n;++j)if(j+det>=1&&j+det<=n)
add(a[j][j+det],x[i],0,3),add(x[i],a[j][j+det],0,3);
}
for(ri sum,i=1;i<=n*2-1;++i){
val[y[i]=++tot]=1,sum=i+1;
for(ri j=1;j<=n;++j)if(sum-j>=1&&sum-j<=n)
add(a[j][sum-j],y[i],0,3),add(y[i],a[j][sum-j],0,3);
}
solve();
return 0;
}
E题
传送门
题意:给一个长度为n,字符集为A的字符串,以及m个数字b,对于任意数字bib_ibi足长度为bib_ibi的前缀和后缀先反转再交换位置后形成的新串与原串视作相等,问存在多少不同串。
思路:把bbb排序,然后方案只跟起差分数列有关,显然对于两个长度都等于某一个bib_ibi的串A,BA,BA,B如果A<BA<BA<B就可以产生一次贡献。
于是只用处理询问一个f(x)f(x)f(x)表示从长度为xxx的所有串中选出来两个,A<BA<BA<B的方案。
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef long long ll;
const int N=2e5+5,mod=998244353,inv2=499122177;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)ret=mul(ret,a);return ret;}
int n,m,a,b[N],ans;
inline int f(const int&x){int tmp=ksm(a,x);return mul(mul(tmp,tmp+1),inv2);}
int main(){
n=read(),m=read(),a=read();
for(ri i=1;i<=m;++i)b[i]=read();
ans=mul(ksm(a,n-2*b[m]),f(b[1]));
for(ri i=2;i<=m;++i)ans=mul(ans,f(b[i]-b[i-1]));
cout<<ans;
return 0;
}
F题
传送门
题意:给你一棵树。
你从根节点111出发有如下两种走法:
- 走到该节点子树中的某个叶子
- 如果你在一个叶子上,可以选择走到你的111~kkk级祖先。
问你最后能够访问到的不同叶子数的最大值。
思路:
吐槽:想长链剖分和线段树想了好久然后突然发现一道NOIP难度的树形dp
gig_igi表示iii向子树中走且最后能回到iii的最大答案,fif_ifi则表示iii向子树中最后不必回到iii的最大答案。
然后从儿子转移一下就完了。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int N=1e6+5;
int n,k,f[N],g[N],dep[N],mndep[N];
vector<int>e[N];
void dfs(int p){
mndep[p]=0x3f3f3f3f;
if(!e[p].size()){f[p]=g[p]=1,mndep[p]=dep[p];return;}
for(ri i=0,v;i<e[p].size();++i){
dep[v=e[p][i]]=dep[p]+1,dfs(v),mndep[p]=min(mndep[p],mndep[v]);
if(mndep[v]-dep[p]<=k)g[p]+=g[v],f[p]+=g[v];
}
int sum=f[p];
for(ri i=0,v;i<e[p].size();++i)f[p]=max(f[p],sum-(mndep[v=e[p][i]]-dep[p]<=k?g[v]:0)+f[v]);
}
int main(){
n=read(),k=read();
for(ri i=2;i<=n;++i)e[read()].push_back(i);
dfs(1);
cout<<max(f[1],g[1]);
return 0;
}
G题
传送门
题意:给你一个字符串斐波那契数列,F0=F_0=F0="000",F1=F_1=F1="111",Fi=Fi−2+Fi−1F_i=F_{i-2}+F_{i-1}Fi=Fi−2+Fi−1,令AFiA_{F_i}AFi表示这个串的所有后缀排序后的序列,问这个序列第kkk项的前mmm个字符。
思路:
我们相当于二分一样每次按位考虑走0/10/10/1就完了。
代码(照着zhouoyuyang{\color {red}zhouoyuyang}zhouoyuyang的码了一遍):
#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
const int N=305;
const ll lim=1e18+1;
int n,m;
ll k;
string ans="",f[15];
inline bool pre(int pos,const string&s,int st,const ll&len){
int id=pos<=14?pos:14-(pos&1);
return len<=f[id].size()&&!f[id].compare(0,len,s,st,len);
}
inline bool suf(int pos,const string&s,int st,const ll&len){
int id=min(pos,14);
return len<=f[id].size()&&!f[id].compare(f[id].size()-len,len,s,st,len);
}
inline ll calc(const int&n,const string&s){
static ll g[N];
for(ri i=0;i<=n;++i){
if(i<2){g[i]=f[i]==s;continue;}
g[i]=g[i-1]+g[i-2];
for(ri up=s.size(),j=1;j<up;++j)if(suf(i-2,s,0,j)&&pre(i-1,s,j,up-j))++g[i];
g[i]=min(g[i],lim);
}
return g[n];
}
int main(){
f[0]="0",f[1]="1";
for(ri i=2;i<=14;++i)f[i]=f[i-2]+f[i-1];
scanf("%d%lld%d",&n,&k,&m);
ll cnt0,ext;
for(ri i=1;i<=m;++i){
cnt0=calc(n,ans+'0');
ll ext=ans!=""&&suf(n,ans,0,ans.size());
if(k<=ext)break;
if(k<=ext+cnt0)k-=ext,ans+='0';
else k-=ext+cnt0,ans+='1';
}
cout<<ans;
return 0;
}
Codeforces 1065 简要题解的更多相关文章
- Codeforces 863 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 简要题解?因为最后一题太毒不想写了所以其实是部分题解... A题 传送门 题意简述:给你一个数,问你能不能通过加前导000使其成为一个回文数 ...
- Codeforces 381 简要题解
做的太糟糕了...第一题看成两人都取最优策略,写了个n^2的dp,还好pre-test良心(感觉TC和CF的pretest还是很靠谱的),让我反复过不去,仔细看题原来是取两边最大的啊!!!前30分钟就 ...
- Codeforces 1120 简要题解
文章目录 A题 B题 C题 D题 E题 F题 传送门 A题 传送门 题意简述:给你一个mmm个数的数列,现在规定把一个数列的1,2,...,k1,2,...,k1,2,...,k分成第一组,把k+1, ...
- Codeforces 1098 简要题解
文章目录 前言 A题 B题 C题 D题 E题 传送门 前言 没错因为蒟蒻太菜了这场的最后一道题也咕掉了,只有AAA至EEE的题解233 A题 传送门 题意简述:给出一棵带点权的树,根节点深度为111, ...
- Codeforces 1110 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 众所周知ldxoildxoildxoi这种菜鸡选手是不会写HHH题的,因此该篇博客只有AAA题至GGG题的题解,实在抱歉. A题 传送门 题 ...
- Codeforces 380 简要题解
ABC见上一篇. 感觉这场比赛很有数学气息. D: 显然必须要贴着之前的人坐下. 首先考虑没有限制的方案数.就是2n - 1(我们把1固定,其他的都只有两种方案,放完后长度为n) 我们发现对于一个限制 ...
- Codeforces 845 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 A题 传送门 题意:2n2n2n个人下棋,分为两个阵营,每个阵营nnn个人,每个人有一个积分,积分高的能赢积分低的,问如果你可以随意选人,然 ...
- Codeforces 888 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 A题 传送门 题意简述:给一个数列,问有多少个峰值点(同时比两边都大/小的点) 思路:按照题意模拟. 代码: #include<bit ...
- Codeforces 884 简要题解
文章目录 A题 B题 C题 D题 E题 F题 传送门 A题 传送门 题意简述: 一个人要完成一件事总共需要ttt秒,现在有nnn天,每天有aia_iai不能做事,问他可以在第几天做完. 思路:按照题 ...
随机推荐
- U3D 设置帧率与垂直同步
1,设置帧率: Application.targetFrameRate = 60: //-1为无限制 2,垂直同步 project settings -> quality,任何level的垂直同 ...
- fopen特殊模式r+, w+, a+辨析
fopen模式分两大类,即 TEXT模式:r, w, a, r+, w+, a+ BIN模式:rb, wb, ab, r+b, w+b, a+b 模式 读指针初始位置 写指针初始位置 模式用途 详细说 ...
- could not open input file 错误
配置laravel时遇到的小错误 ps:php -S localhost:81 -t 框架目录/public S大写 端口不要被占用
- Intel 82599网卡异常挂死原因
前提背景: 生产环境上,服务器网络突然断链,ssh连接失败. 问题初步定位: 查找内核日志,得到网卡异常信息 Jan 24 11:52:43 localhost kernel: ixgbe 0000: ...
- Django SCRF跨站点请求伪造
使用Django发POSTt请求的时候经常会遇到Forbidden的错误,然后直接了当的方法就是去setting里面吧csrf中间件注释掉,其实csrf是django给我们提供的防护措施. CSRF就 ...
- python的django基础篇
一.Django基础 Django 是用Python开发的一个免费开源的Web框架,可以用于快速搭建高性能,优雅的网站! Django的特点: 强大的数据库功能:拥有强大的数据库操作接口(QueryS ...
- python--第十五天总结(jquery)
空格:$('parent childchild')表示获取parent下的所有的childchild节点,所有的子孙. 大于号:$('parent > child')表示获取parent下的所有 ...
- linux下mycat自启动方法
每次开机都要启动mycat,网上看了好多都是用shell脚本来实现mycat开机自启动,后来看到一种方法,直接修改系统文件来实现,已经实践过,方法有效. 1.修改脚本文件rc.local:vim /e ...
- 下拉js的实现
这个JS是出自一个浴室柜网站 $(document).ready(function(){ $(".side_nav_3").hover(function() { $(this).f ...
- vue使用qrcode插件生成二维码
参考:https://www.jianshu.com/p/d3883e020d99 步骤: 第一步:vue-cli下载插件 cnpm install --save qrcodejs2 第二步:组件中引 ...