无关前置

最近同学都在打牛客网的比赛并且博主也在写一下牛客网的题,博主就去看了看,打了一场,题目质量还是非常不错的。我才不会告诉你我没开long long错了好久QWQ


  • 212A-灰魔法师

题意简述

给出长度为nnn的序列aaa, 求有多少对数对 (i,j)(1≤i&lt;j≤n)(i, j) (1 \leq i &lt; j \leq n)(i,j)(1≤i<j≤n) 满足 ai+aja_i + a_jai​+aj​ 为完全平方数。

数据范围:1≤n,a≤1051\leq n,a\leq10^51≤n,a≤105


这个签到题吧,范围十分的小,值域才10510^5105,开个数组记录一下每个数字出现次数,然后n\sqrt{n}n​的每次枚举平方就好啦,复杂度O(nn)O(n\sqrt{n})O(nn​)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=3e5+10;
int n,maxv;ll ans;
int A[M],B[M];
int main(){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&A[i]),maxv=max(A[i],maxv);for(int i=1;i<=n;i++){for(int j=1;j*j<=(maxv<<1);j++){if(j*j-A[i]<0) continue;ans+=B[j*j-A[i]];}++B[A[i]];}printf("%lld\n",ans);return 0;
}

  • 212B-紫魔法师

题意简述

给出一棵仙人掌(每条边最多被包含于一个环,无自环,无重边,保证连通),要求用最少的颜色对其顶点染色,满足每条边两个端点的颜色不同,输出最小颜色数即可

数据范围

n≤100000,m≤200000n\leq 100000, m \leq 200000n≤100000,m≤200000(nnn为点数,mmm为边数)


这个稍微推一下就知道了,本来这个问题在一般的无向图上,是非常难解决的,但是我们看,这是一个仙人掌,只有简单环。所以对于所有的环,如果有奇数点环,那么至少用三种颜色;如果所有环点数都为偶数,那么至少用两种颜色。由于是简单环,深搜一遍即可统计答案。

#include<cstdio>
#include<cstring>
#include<algorithm>using namespace std;
const int M=2e5+10;
int n,m;
struct ss{int to,last;ss(){}ss(int a,int b):to(a),last(b){}
}g[M<<1];
int head[M],cnt;
void add(int a,int b){g[++cnt]=ss(b,head[a]);head[a]=cnt;g[++cnt]=ss(a,head[b]);head[b]=cnt;
}
bool vis[M];
int dfn[M],tim,ans;
void dfs(int a,int b){if(ans==3) return;dfn[a]=++tim;vis[a]=1;for(int i=head[a];i;i=g[i].last){if(g[i].to==b) continue;if(!vis[g[i].to]){dfs(g[i].to,a);}else{int now=dfn[a]-dfn[g[i].to]+1;if((now&1)&&ans<3)ans=3;if(!(now&1)&&!ans)ans=2;}}
}
int a,b;
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);add(a,b);}if(!n){puts("0");return 0;}if(n==1){puts("1");return 0;}for(int i=1;i<=n;i++){if(!dfn[i]){dfs(i,i);if(ans>=3) break;}}printf("%d\n",ans);return 0;
}

  • 215C-蓝魔法师

题意简述

给出一棵nnn个点的树,求有多少种删边方案,使得删后的图每个连通块大小小于等于kkk,两种方案不同当且仅当存在一条边在一个方案中被删除,而在另一个方案中未被删除,答案对998244353998244353998244353取模

数据范围:2≤n,k≤20002\leq n,k\leq 20002≤n,k≤2000


这个就是个裸的树上背包问题,我们定义状态f[i][j]f[i][j]f[i][j],表示以iii为根的子树,连通块大小为jjj的方案数,其中我们特殊规定当j=0j=0j=0时,表示iii点不与上方父亲结点连通的方案数,所以就深搜一遍,树形DP\rm DPDP,复杂度看似最坏为n3n^3n3,实际上由于每次枚举不是枚举所有的点数,所以复杂度大概算下来为n2∼n53n^2\sim n^\frac{5}{3}n2∼n35​左右,是不会达到n3n^3n3的,所以完全能够(具体的一些证明可以去网上找一些树上背包的题的题解,里面可能有)。

所以直接打就好了,不要害怕超时。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k;
const int N=4010;
const int Mod=998244353;
struct ss{int to,last;ss(){}ss(int a,int b):to(a),last(b){}
}g[N<<1];
int head[N],cnt;
void add(int a,int b){g[++cnt]=ss(b,head[a]);head[a]=cnt;g[++cnt]=ss(a,head[b]);head[b]=cnt;
}
int dp[N][N],sze[N],sum[N],ls[N];
void dfs(int a,int b){sze[a]=1;dp[a][1]=1;for(int i=head[a];i;i=g[i].last){if(g[i].to==b) continue;dfs(g[i].to,a);for(int x=min(sze[a]+sze[g[i].to],k);x>=0;x--)ls[x]=0;for(int x=min(sze[a],k);x>=1;x--){for(int y=min(sze[g[i].to],k-x);y>=0;y--){ls[x+y]=(ls[x+y]+1ll*dp[a][x]*dp[g[i].to][y]%Mod)%Mod;}}sze[a]+=sze[g[i].to];for(int x=min(sze[a],k);x>=0;x--)dp[a][x]=ls[x];}for(int i=min(sze[a],k);i>=1;i--)dp[a][0]=(dp[a][0]+dp[a][i])%Mod;
}
int ans,a,b;
int main(){scanf("%d%d",&n,&k);for(int i=1;i<n;i++){scanf("%d%d",&a,&b);add(a,b);}dfs(1,0);printf("%d\n",dp[1][0]);return 0;
}

  • 215D-绿魔法师

题意简述

给你一个空的可重集,nnn次操作,每次操作给出x,k,px,k,px,k,p,执行以下操作:

  1. 在SSS中加入xxx
  2. 输出∑y∈Sgcd(x,y)k(modp)\sum\limits_{y\in S}gcd(x,y)^k(\rm mod\ p)y∈S∑​gcd(x,y)k(mod p)

1≤n,x,k,p≤1051\leq n,x,k,p\leq 10^51≤n,x,k,p≤105


显然暴力就为O(n2logn)O(n^2logn)O(n2logn)
但是我们这里考虑,gcdgcdgcd为最大公约数,所以一定为给出数字的因子,而在10510^5105内的一个数字的因子数量不会很多(可以自己用线性筛筛一遍看看),所以我们考虑将每个插入的数拆成因子插入,然后我们从大到小枚举它的因子,因为对于一个它的因子,如果当前枚举的肯定是较大的,当这个因子有的时候,那么肯定会成为答案,记这个因子为aaa,出现个数为ccc,那么贡献为c×(ak)c\times (a^k)c×(ak),然后统计完这个我们需要把这个因子的因子的个数全部减去ccc,因为包含该因子的数字我们已经算了,不能重复算,而后面只会枚举比它小的数,所以只用减去它的因子的数。

我们每次n\sqrt{n}n​的统计因子,然后记最多因子个数为www,每次w2w^2w2的统计答案,然后加一点常数优化和剪枝,就可以过了,复杂度O(nn×w2)O(n\sqrt{n}\times w^2)O(nn​×w2),但是注意这里的w2w^2w2是远远达不到的。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define int long long
using namespace std;
const int N=1e5+10;
int n,p;
int cnt[N],del[N];
vector <int> vec[N];
int fpow(int a,int b){int ans=1;for(;b;b>>=1,a=(1ll*a*a)%p){if(b&1)ans=(1ll*ans*a)%p;}return ans%p;
}
void add(int x){int a=sqrt(x);if(!vec[x].size()){for(int i=1;i<=a;i++){if(!(x%i)){vec[x].push_back(i);++cnt[i];if((x/i)!=i){vec[x].push_back(x/i);++cnt[x/i];}}}}else{for(int i=0,sz=vec[x].size();i<sz;i++)++cnt[vec[x][i]];}
}
void calc(int x){int a=sqrt(x);for(int i=1;i<=a;i++){if(!(x%i)){vec[x].push_back(i);if((x/i)!=i){vec[x].push_back(x/i);}}}
}
bool is_sort[N];
int query(int x,int k){memset(del,0,sizeof(del));int ans=0;if(!is_sort[x])is_sort[x]=1,sort(vec[x].begin(),vec[x].end());for(int i=vec[x].size()-1;i>=0;i--){int a=vec[x][i];if(cnt[a]<=del[a]) continue;ans=(ans+(cnt[a]-del[a])*fpow(a,k)%p)%p;if(!vec[a].size())calc(a);int now=cnt[a]-del[a];if(i)for(int j=0,sz=vec[a].size();j<sz;j++){if(vec[a][j]>a) break;del[vec[a][j]]+=now;if(i&&vec[a][j]==vec[x][i-1]&&cnt[vec[x][i-1]]<=del[vec[x][i-1]])--i;}}return ans;
}
int x,k;
signed main(){scanf("%lld",&n);for(int i=1;i<=n;i++){scanf("%lld%lld%lld",&x,&k,&p);add(x);cout<<query(x,k)<<'\n';}return 0;
}

  • 215E-黄魔法师

题意简述

给出 n,kn, kn,k,求一个长度为 nnn 的数组 aaa, 满足有恰好 kkk 对数对 (i,j)(1≤i&lt;j≤n)(i, j) (1 \leq i &lt; j\leq n)(i,j)(1≤i<j≤n)满足 ai+aja_i + a_jai​+aj​为完全平方数。如果不存在,输出 −1-1−1 。

数据范围: n≤105,k≤1010n\leq 10^5,k\leq 10^{10}n≤105,k≤1010


这个题非常的良心啊,第一题的标程就是它的检验器啊。

我们首先分析,对于无解的情况,当你无论如何都凑不到kkk个时就无解,所以对于一个长度为nnn的序列,它最多能组合出n×(n−1)2\frac{n\times(n-1)}{2}2n×(n−1)​个完全平方数,所以当k&gt;n×(n−1)2k&gt;\frac{n\times(n-1)}{2}k>2n×(n−1)​我们就可以判断它无解。

然后对于有解的情况,由于只让输出一种方案,所以我们特殊构造即可,首先我们找几个数字xxx,xxx要满足2x2x2x为完全平方数,然后因为数字可以重复,所以如果我们放了iii个xxx,那么它就会有i×(i−1)2\frac{i\times(i-1)}{2}2i×(i−1)​的贡献。

所以我们分类讨论,对于kkk可以写成i×(i−1)2\frac{i\times(i-1)}{2}2i×(i−1)​的形式的情况,我们直接输出iii个xxx,然后找一个yyy,满足2y2y2y和x+yx+yx+y都不为完全平方数,剩下的n−in-in−i个数字由这个数字填充即可。

然后对于kkk不能写成i×(i−1)2\frac{i\times(i-1)}{2}2i×(i−1)​的形式的情况,我们可以多选几种xxx,然后先凑成近似kkk,剩下的我们找一个www,满足w+其中一个xw+\text{其中一个}xw+其中一个x为完全平方数,而2w2w2w不为完全平方数,那么它就可以贡献出选的那个xxx的个数那么多的完全平方数,不难发现,这样一定能凑到kkk,剩下的同理选一个和其它已经选的xxx,还有自己都不能组成完全平方数的数字填充即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=1e5+10;
ll n,k,top,p;
ll ans[M];int main(){scanf("%lld%lld",&n,&k);if(n*(n-1)/2<k){puts("-1");return 0;}for(;top*(top-1)/2<=k;++top);--top;ll res=k-top*(top-1)/2;if(!res){for(int i=1;i<=top;i++)ans[++p]=2;while(p<n)ans[++p]=3;}else{for(int i=1;i<=top-res;i++)ans[++p]=98;for(int i=1;i<=res;i++)ans[++p]=2;ans[++p]=7;while(p<n)ans[++p]=5;}for(int i=1;i<=n;i++)printf("%lld ",ans[i]);return 0;
}
  • 215F-红魔法师

题意简述

一个空的二维平面上,每次加入或删除一个整点。
求每次操作完之后满足以下条件的三个点p1,p2,p3p_1,p_2,p_3p1​,p2​,p3​的对数。

  1. p1.y&gt;p2.y&gt;p3.yp_1.y&gt;p_2.y&gt;p_3.yp1​.y>p2​.y>p3​.y
  2. p1.x&gt;max(p2.x,p3.x)p_1.x&gt;max(p_2.x,p_3.x)p1​.x>max(p2​.x,p3​.x)

令操作数为nnn,保证n≤60000,1≤x,y≤nn\leq 60000,1\leq x,y\leq nn≤60000,1≤x,y≤n。
保证加入点的时候平面上没有该点。
保证删除点的时候平面上有该点。

这个题由于有点难写以及比赛已经结束就没有写QWQ,所以这里口胡一下


暴力就不说了。

我们首先看统计的条件,十分特别,对于一个点,我们把它当做p1p_1p1​,那么就只统计它的左下方的点对,且满足p2.y&gt;p3.yp_2.y&gt;p_3.yp2​.y>p3​.y即可。

所以我们先用离线,排序,扫描线预处理,然后用三维或者二维偏序之类的统计答案即可。

比赛Rank1后面是切了这个题的,牛客网的代码是公开的,所以想看代码的可以去牛客网看。


End

没有抽到T桖QAQ,虽然冬天,但是还是想要啊QWQ

牛客网比赛-Wannafly挑战赛27相关推荐

  1. 牛客网习题集 - Wannafly挑战赛13- D applese生日

    链接:点击打开链接 题目描述 最可爱的applese生日啦,他准备了许多个质量不同的蛋糕,想请一些同学来参加他的派对为他庆生,为了不让一部分同学感到不爽,他决定把每个蛋糕都分割成几份(也可以不分割), ...

  2. 牛客网习题集 - Wannafly挑战赛13- Jxc军训

    在文某路学车中学高一新生军训中,Jxc正站在太阳下站着军姿,对于这样的酷热的阳光,Jxc 表示非常不爽. Jxc将天空看做一个n*n的矩阵,此时天上有m朵云,这些云会随机分布在m个不同的位置,同时太阳 ...

  3. 牛客网 Wannafly挑战赛27 蓝魔法师

    蓝魔法师 链接: https://www.nowcoder.com/acm/contest/215/C 来源:牛客网 题目描述 "你,你认错人了.我真的,真的不是食人魔."--蓝魔 ...

  4. 题解——牛客网Wannafly挑战赛23 B-游戏 (SG函数)

    前言 比赛的时候没学过SG函数的蒟蒻以为是道结论题,但是不是QwQ 和dummyummy巨佬一起推了快三个小时的规律 最后去问了真正的巨佬__stdcall __stdcall面带微笑的告诉我们,这是 ...

  5. 牛客网 Wannafly挑战赛8 A.小Y和小B睡觉觉

    写了一会不想写了... A-小Y和小B睡觉觉 链接:https://www.nowcoder.com/acm/contest/57/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制 ...

  6. 牛客网 Wannafly挑战赛20 A-染色

    链接:https://www.nowcoder.com/acm/contest/133/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...

  7. 牛客网wannafly挑战赛13-D(贪心)

    链接:https://www.nowcoder.com/acm/contest/80/D 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...

  8. 牛客网wannafly挑战赛13-E(线段树)

    链接:https://www.nowcoder.com/acm/contest/80/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...

  9. 牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) H.Tree Recovery-完全版线段树(区间更新、区间求和)...

    H.Tree Recovery 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言262144K 64bit IO Format: %lld 链接:https:/ ...

最新文章

  1. 爬虫学习笔记(二十一)—— Appium
  2. 496. 下一个更大元素 I
  3. Codeforces Round #528 (Div. 2) - D. Minimum Diameter Tree
  4. 细节决定成败—关于.net的.dll.refresh文件
  5. mac SecureCRT设置
  6. html filter 在线预览,HTML Filter
  7. 【BZOJ1060】【codevs1435】时态同步,我可以叫它树形递推吗
  8. Spark参数配置说明
  9. TensorFlow:判断CUDA和GPU是否可用
  10. NVIDIA TK1 刷机记录(1)ubuntu 14.04
  11. 论文阅读(12) 与其他后生动物相比,水母被动能量的重新获取有助于推进优势(2013)
  12. 《微观经济学》第一章经济学十大原理
  13. 计算机主板提示ahci,映泰主板设置硬盘模式AHCI或IDE的教程
  14. 戴尔服务器提升性能,解析戴尔12G服务器的主要性能提升和改进
  15. iPhone升级系统 死机了怎么办
  16. unniapp实现电子签名
  17. docker保存镜像、打包tar、加载tar镜像
  18. Arcpy实现批量制图
  19. 电脑在线一键安装win10系统教程分享
  20. linux卸载bzip2,Linux命令(29):bzip2/bunzip2命令-压缩和解压

热门文章

  1. DNS 安全信息 (微软)
  2. CommonTableCollectView:使用例子,增删cell,以及label解析html
  3. 什么是高并发?与多线程有什么区别?你的项目有高并发问题吗?是如何解决的?
  4. Delphi 注册表操作
  5. uniapp微信小程序和打包app的分享功能
  6. 速记-北斗与galileo频率波长
  7. kong DB-LESS和DB模式的对比
  8. python—webp图片格式转换为jpg
  9. Flink学习笔记-阿里云Blink
  10. 2017年全国大学生电子设计大赛A题(微电网模拟系统)