【题解】牛客练习赛60

A.大吉大利

我们按位考虑,那么每一位的贡献就是在二进制下这一位在个数中出现的次数的平方乘上二进制的系数。

B.三角形周长和

也是一道签到题,但是边长改成了曼哈顿距离,至于为什么,完全是因为我不想写std去判精度。
因为是1000,所以直接去枚举所有边,那么每一条边显然会在其他个三角形中出现,这个就是这条边的贡献系数,这题就算完了。

C.操作集锦

求长度为的字符串的长度为的子序列。我们考虑用表示考虑前个字符形成的长度为的子序列个数。
那么如果我们不考虑会重复的情况,转移方程是
那么显然是多算一部分重复的,我们记录表示这个字符之前出现的位置,那么多算的这部分很容易发现就是

D.斩杀线计算大师

算是出了一道假题,正解应该是同余最短路。介绍一下做法吧,现在是要求,那么我们设,那么显然我们只需要凑出就行了,考虑到的余数。因此的取值范围是。那么我们不妨设表示用可以凑出的最小的数。不难发现
,。如果我们对每个下标都对取模,可以发现转移变成了以及。容易发现这恰好是最短路的转移,因此我们用的每个数作为数组下标,然后去跑最短路就能得到合法的方案。注意在跑最短路的时候记录路径的转移,这样就能通过去求解答案。复杂度是
额,这道假题应该是源于我图论实在是太差了,导致很多图论的做法都没有了解过。

E.旗鼓相当的对手

或者长链剖分应该都可以做。我写的std是用的。因为是查询节点不同子树中距离为的点对,因此我们只需要用一个数组来记录某个点的深度值,那么每次询问相当于查询所有深度为的其他子树的节点产生的贡献。
感觉实在是非常的裸,所以难点在于,有其他疑问可以提出来。

F.几何带师

总的来说这题我是要谢罪的。因为三点不共线的话,用std的做法有产生精度误差,其实可以避免这个精度误差,但是码量会比较大,因此我花了一天时间去造不存在三点共线的数据。
最后虽然找到了一个方法,但是在写数据生成器的时候,没有判重点,因此数据中存在重点。又因为的数据是难以验证是否存在三点共线的,因此我就用纯暴力去和std对跑,然后所有数据都通过了,这是我没有想到的,在std和暴力对上的情况下,我就相信了数据中是不存在重点的。不过还好是最后一题,没有影响排名。下面讲一下做法。
我们已经两个定点,现在我们需要判断直线是否和线段相交。现在我们考虑一下同侧的情况。那么必定存在或者中。
我们就假设中好了,设分别表示的角度。设分别表示。那么中当且仅当。不难发现这是一个二维偏序,我们对其中一维排序然后用统计即可。
当满足异侧的时候,则是两个外角满足大小关系,画图可以很容易发现。
全部评论
貌似T4直接暴力枚举z从1~10^5是可做的 假设存在一组解x,y,z,满足z>10^5 由ax+by+cz = k,等式变下形就有a(x + c) + by + c(z - a) = k 显然z最小可以是z % a,而这个值是小于10^5的,所以一定存在一组解使得z小于10^5 piapia打脸啊😅
1 回复 分享
发布于 2020-03-30 20:12
膜出题人(d水过去的屑->我
点赞 回复 分享
发布于 2020-03-27 23:50
D题题解假了吧,塞瓦韦斯特定理是干什么的orz。用std尝试一下a=6,b=8,c=2,k=10。 (不过话说我就是这么写的,只是用ab bc ac分别跑了一次,欢迎大家来hack我orz,我自己证证不出来)
点赞 回复 分享
发布于 2020-03-28 00:17
请问出题人,B题这样写为什么过不了所有测试点呢?感觉与题解没有什么差别。 #include<bits/stdc++.h> using namespace std; const int m = 998244353; int n; long long Edge,ans=0; pair<int,int> node[1005]; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>node[i].first>>node[i].second; } for(int i=1;i<=n-1;i++) { for(int j=i+1;j<=n;j++) { Edge = abs(node[i].first - node[j].first)+abs(node[i].second - node[j].second); ans = (ans+(n-2) * Edge) % m; } } cout<<ans; return 0; }
点赞 回复 分享
发布于 2020-03-28 09:39
#include <bits/stdc++.h> using namespace std; const int N=1e3+5,MOD=1e9+7; int n,k,ans; int f[N][N]; bool vis[27]; char str[N]; int main(){ scanf("%d%d",&n,&k); scanf("%s",str+1); for (register int i=1; i<=n; ++i) { f[i][1]=1; for (register int j=1; j<=k; ++j) { memset(vis,false,sizeof(vis)); int now=i-1; while (now)  { if (!vis[str[now]-'a'+1]) f[i][j]=(f[i][j]+f[now][j-1])%MOD,vis[str[now]-'a'+1]=true; now--; } } } memset(vis,false,sizeof(vis)); for (register int i=n; i>=1; --i) if (!vis[str[i]-'a'+1]) vis[str[i]-'a'+1]=true,ans=(ans+f[i][k])%MOD; if (k==0) ans=1; printf("%d\n",ans); return 0; }
点赞 回复 分享
发布于 2020-03-28 10:31
为什么C题这样能过啊emm。。。
点赞 回复 分享
发布于 2020-03-28 10:31
D题正解为什么要枚举第三个数啊
点赞 回复 分享
发布于 2020-03-28 11:56
裴蜀定理指出,ax+by=c有解的充要条件是(a,b)|c,但是却没有指出一定存在一个x,y都是非负整数的解 按照你的说法,x只需要枚举[ 0 , gcd(b,c) ),而5x+7y+11z=23这组数据就可以把你卡掉,当我枚举x=0时,23-5*0是可以被gcd(7,11)整除的,而且7y+11z=23也确实有解(y=-69,z=46),却没有非负整数对的解 也就是并不能保证x枚举到[ 0,gcd(b,c) )就能出答案
点赞 回复 分享
发布于 2020-03-29 00:21
D用扩欧写了一下,没发现什么bug,谁能给我找个数据hack一下我代码吗?谢谢啦! https://ac.nowcoder.com/acm/contest/view-submission?submissionId=43271960
点赞 回复 分享
发布于 2020-03-30 11:40
本人小白~  请问下c题最后 判断res<0怎么想的?有没有可能res加上mod还是负的?咋证明啊?
点赞 回复 分享
发布于 2020-03-30 14:02
C 题题解没我写得好(/doge
点赞 回复 分享
发布于 2020-03-30 20:59
“那么我们不妨设dp[i]表示用a, b可以凑出的最小的数。”感觉这句话说得好奇怪,dp[i]的i表示什么?dp[i]怎么就表示a, b可以凑出的最小的数。那dp[j]表示什么?
点赞 回复 分享
发布于 2020-03-31 20:39
C不是原题嘛!! https://www.luogu.com.cn/problem/CF1183H 我真的无语!!!
点赞 回复 分享
发布于 2020-04-20 14:08

相关推荐

已老实求offer😫:有点像徐坤(没有冒犯的意思哈)
点赞 评论 收藏
分享
6 5 评论
分享
牛客网
牛客企业服务