2020 wannafly camp 补题 day1
题目可以从牛客上找到。
最简单的一个题应该是B
B. 密码学
这个应该就是倒着推,题目给了你加密的顺序,所以我们逆推这个就可以得到每一次加密前的字符串。
1H. 最大公约数
题目大意就是给你一个范围1~n 满足gcd(k,y) 是独一无二的,意思是除了k之外,1~n中没有gcd(i,y)==gcd(k,y)
这个题目首先要知道gcd(k,y)==k,因为如果等于x,且x<k,那么因为x属于1~n,所以gcd(x,y)==x
这样就不满足题目要求了。
所以y一定是k的倍数,因为在这n个数中,可能有很多数都是k的整数倍,那么这个y要满足要求,则必须是
gcd(m*k,y)!=k,所以如果有数是k的素数倍,那么y也一定是这个素数的倍数。
这个会爆long long 。
F. 乘法
这个算法是二分,二分这个第k大,然后check。
这个check有点难写,因为有正有负需要分开写。
最后对我来说比较坑的地方是因为取过膜,所以不可以直接除以2,需要乘以2的逆元。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<bits/stdc++.h>
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=1e5+;
typedef long long ll;
ll a[maxn],b[maxn];
ll a1[maxn],a2[maxn],b1[maxn],b2[maxn];
ll tota1=,tota2=,totb1=,totb2=,zera=,zerb=;
ll n,m,k;
bool check(ll x){
ll sum=;
if(x<=){
sum+=tota1*totb1+tota2*totb2+zera*m+zerb*n-zera*zerb;
// printf("sum=%lld\n",sum);
if(x==) return sum>=k;
if(sum>=k) return true;
x=-x;
for(int i=;i<=tota1&&totb2;i++){
ll t=upper_bound(b2+,b2++totb2,x/a1[i])-b2;
if(b2[t]>x/a1[i]||t>totb2) t--;
sum+=t;
// printf("aa i=%d sum=%lld t=%d %d\n",i,sum,t,totb2);
}
for(int i=;i<=tota2&&totb1;i++){
ll t=upper_bound(b1+,b1++totb1,x/a2[i])-b1;
// printf("t=%d\n",t);
if(b1[t]>x/a2[i]||t>totb1) t--;
sum+=t;
// printf("i=%d sum=%lld t=%d\n",i,sum,t); }
// printf("x=%lld sum=%lld\n",x,sum);
return sum>=k;
}
for(int i=;i<=tota1&&totb1;i++){
ll val=x/a1[i];
if(x%a1[i]) val++;
int t=lower_bound(b1+,b1++totb1,val)-b1;
sum+=totb1-t+;
}
for(int i=;i<=tota2&&totb2;i++){
ll val=x/a2[i];
if(x%a2[i]) val++;
int t=lower_bound(b2+,b2++totb2,val)-b2;
sum+=totb2-t+;
}
return sum>=k;
}
int main(){
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=;i<=n;i++) scanf("%lld",&a[i]);
for(int i=;i<=m;i++) scanf("%lld",&b[i]);
for(int i=;i<=n;i++){
if(a[i]<) a1[++tota1]=-a[i];
else if(a[i]>) a2[++tota2]=a[i];
else zera++;
}
for(int i=;i<=m;i++){
if(b[i]<) b1[++totb1]=-b[i];
else if(b[i]>) b2[++totb2]=b[i];
else zerb++;
}
sort(a1+,a1++tota1);
sort(a2+,a2++tota2);
sort(b1+,b1++totb1);
sort(b2+,b2++totb2);
// printf("%d %d %d %d\n",tota1,tota2,totb1,totb2);
ll l=-inf64,r=inf64,ans=;
while(l<=r){
ll mid=(l+r)>>;
if(check(mid)) ans=mid,l=mid+;
else r=mid-;
}
printf("%lld\n",ans);
return ;
}
/*
1 2 2
2
-3 -3 */
F
A期望逆序对
这个是要求逆序对尽可能少,虽然说是期望,但其实就是通过对这些区间进行重新排序,然后减少逆序对。
这是一个贪心题目,如何减少逆序对呢,这个可以通过排序,不过这个排序方式有点难想。
然后就是求期望。
最后很坑的一点是这个题目只可以n*n,卡n*n*logn
而逆元的求法就是一个logn的复杂度。
7-3 1C. 染色图
这个染色图题目不是很难,但是要知道数论分块这个知识点。
数论分块是解决:
这个问题的。复杂度是o(n)
写法很简单
int ans = 0;
for(int l = 1, r = 0; l <= n; l++) {
r = n / (n / l);
// do something
}
知道这个之后推一下这个公式就可以算出答案,这个公式很好推的。
推公式:
假设只有三种颜色,A颜色有x个点,B颜色有y个点,C颜色有z个点。
则 x+y+z=n 一共可以连的边是 [x*(n-x)+y*(n-y)+z*(n-z)]/2
可以推出时 [n*n-x*x-y*y-z*z]/2
因为x+y+z=n 所以如果 x=y=z=n/3 则是最少的边。
然后就可以转化成数论分块要解决的问题。
这些是在camp补的题目,具体代码等回家再补。
E 树与路径
在家里补了一下这个E题,这个是看着题解补的,还看了标程才看懂。
这个题目类似于树上差分,不过比裸的差分要难很多。
设 Ai 为以 i 为根节点,所有路径的权值和。
考虑两种情况:
1) 当 i 和 fi 在同一条路径上时,是不是 Ai=Afi
2) 当 i 和 fi 不在同一条路径上的时候,假设i 往下走的长度为 x,这条路径的长度为s
所以Ai=x*(s-x) Afi=(x+1)*(s-x-1)
所以 Ai-Afi=2*x+1-s
所以对于路径 (u,v)来说,设k为u,v的最近公共祖先,这条路对于 Au的贡献是1-s,对于Afu的贡献是 3-s
所以可以求出在u->k 这条路径的 i 来说贡献就是 2*(du-di)+1-s
所以就是 -2*di+2*du+1-s,因为1+2*du-s是一个定值,所以可以设为常数 b,di是一个变化的量,-2也是一个定值设为a
所以就是 a*di+b,因为 a1*di+b1+a2*di+b2=(a1+a2)*di+b1+b2
所以就可以直接合并求解。因为在两个根节点的位置a和b都加了一部分,所以需要在根节点的位置减去这一部分,这个就是树上差分的思想。
因为求的是边,所以在根节点把所有加上去的都可以直接减去。
写完了,这个题目我觉得比较难的地方就是去分情况讨论,
因为这个由得到一个点去推其他点的这个套路应该是可以猜得到的,但是怎么去分情况呢,这个我就有点迷茫。
一开始思路很乱,然后看了题解之后决定豁然开朗,不过知道这个情况怎么分之后,就要推这个递推式了。
递推式推出来的方法很多,也有很多不同的变形,但是对于这个题目来说,如果这个递推式唯一的变量就是这个深度,
那么就可以直接进行叠加,就很好写了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <stack>
#include <cmath>
#include <bitset>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#define fir first
#define sec second
using namespace std;
typedef long long ll;
const int maxn=3e5+;
int n,m;
ll a[maxn],b[maxn],ans[maxn],d[maxn];
struct node{
int v,nxt;
node(int v=,int nxt=):v(v),nxt(nxt){}
}e[maxn*];
bool vis[maxn*];
int head[maxn],tot,cnt;
int ver[maxn*],first[maxn*],deep[maxn*];
void add(int u,int v){
e[++cnt]=node(v,head[u]);
head[u]=cnt;
e[++cnt]=node(u,head[v]);
head[v]=cnt;
} int min_(int l, int r) {
return deep[l] < deep[r] ? l : r;
} void dfs(int u, int dep) {
// printf("u=%d dep=%d\n",u,dep);
vis[u] = ;ver[++tot] = u;
deep[tot] = dep;first[u] = tot;
for (int i = head[u]; i != -; i = e[i].nxt) {
int v = e[i].v;
if (!vis[v]) {
d[v]=d[u]+;
dfs(v, dep + );
ver[++tot] = u;deep[tot] = dep;
}
}
}
int dp[maxn*][];
void RMQ(int n) {
for (int i = ; i <= n; i++) dp[i][] = i;
for (int j = ; ( << j) <= n; j++) {
for (int i = ; i + ( << j) - <= n; i++) {
dp[i][j] = min_(dp[i][j - ], dp[i + ( << (j - ))][j - ]);
}
}
}
int LCA(int x, int y) {
int l = first[x];
int r = first[y];
// printf("l=%d r=%d\n",l,r);
if (l > r) swap(l, r);
int k = (log(r - l + 1.0)) / (log(2.0));
int id = min_(dp[l][k], dp[r - ( << k) + ][k]);
return ver[id];
}
void dfs2(int u,int pre){
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].v;
if(v==pre) continue;
dfs2(v,u);
a[u]+=a[v];
b[u]+=b[v];
}
}
void dfs3(int u,int pre){
ans[u]+=a[u]*d[u]+b[u];
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].v;
if(v==pre) continue;
ans[v]=ans[u];
dfs3(v,u);
}
}
int main(){
tot=,cnt=;
memset(head,-,sizeof(head));
memset(d,,sizeof(d));
scanf("%d%d",&n,&m);
for(int i=;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
dfs(,);
RMQ(*n-);
while(m--){
int u,v;
scanf("%d%d",&u,&v);
int k=LCA(u,v);
// printf("u=%d v=%d k=%d\n",u,v,k);
int s=d[u]+d[v]-*d[k];
a[u]-=,b[u]+=+*d[u]-s;
a[v]-=,b[v]+=+*d[v]-s;
a[k]+=,b[k]-=+*d[u]-s++*d[v]-s;
int x=d[u]-d[k];
ans[]+=x*1ll*(s-x);
// printf("s=%d x=%d\n",s,x);
}
// printf("s %lld\n",ans[1]);
dfs2(,-),dfs3(,-);
for(int i=;i<=n;i++) printf("%lld\n",ans[i]);
return ;
}
E
差不多先补到这里,day1 还有一些AC代码没有贴,以后再写吧。
2020 wannafly camp 补题 day1的更多相关文章
- 2020.12.20vj补题
A - Insomnia cure 题意:一共s只龙,每隔k,l,m,n只龙就会受伤,问这s只龙有多少龙是受伤的 思路:看起来题目范围并不是很多,直接进行循环判断 代码: 1 #include< ...
- 2020.12.14vj补题
A. Lucky Ticket 题意:就是说4与7是幸运数字,用4和7组成的数字也是幸运数字,问所给数字是不是幸运数字 思路:直接敲 代码: 1 #include<iostream> 2 ...
- 2020.1.30--vj补题
C - C CodeForces - 991C 题目内容: After passing a test, Vasya got himself a box of n candies. He decided ...
- 2020.11.6-vj补题
A - A CodeForces - 136A 题解:按输入的顺序输出对应的下标即可,定义一个数组,将输入的作为下标,下标为值,最后依次输出即可: #include<bits/stdc++.h& ...
- 【补题记录】ZJU-ICPC Summer Training 2020 部分补题记录
补题地址:https://zjusummer.contest.codeforces.com/ Contents ZJU-ICPC Summer 2020 Contest 1 by Group A Pr ...
- 【JOISC 2020 补题记录】
目录 Day 1 Building 4 Hamburg Steak Sweeping Day 2 Chameleon's Love Making Friends on Joitter is Fun R ...
- 全国信息学奥林匹克联赛 ( NOIP2014) 复赛 模拟题 Day1 长乐一中
题目名称 正确答案 序列问题 长途旅行 英文名称 answer sequence travel 输入文件名 answer.in sequence.in travel.in 输出文件名 answer. ...
- hdu5017:补题系列之西安网络赛1011
补题系列之西安网络赛1011 题目大意:给定一个椭球: 求它到原点的最短距离. 思路: 对于一个椭球的标准方程 x^2/a^2 + y^2/b^2 +z^2/c^2=1 来说,它到原点的最短距离即为m ...
- 2017河工大校赛补题CGH and 赛后小结
网页设计课上实在无聊,便开始补题,发现比赛时候僵着的东西突然相通了不少 首先,"追妹"这题,两个队友讨论半天,分好多种情况最后放弃(可是我连题目都没看啊),今天看了之后试试是不是直 ...
随机推荐
- Github star 1.7k 的项目源码解析
先拜读源码,最后总结,以及其他实现思路.如有错误,欢迎指正! 项目介绍 名称:Darkmode.js 功能:给你的网站添加暗色模式 项目链接:https://github.com/sandoche/D ...
- 【论文笔记】张航和李沐等提出:ResNeSt: Split-Attention Networks(ResNet改进版本)
github地址:https://github.com/zhanghang1989/ResNeSt 论文地址:https://hangzhang.org/files/resnest.pdf 核心就是: ...
- 复杂Excel转换与导入
需求 把不同客户提供Excel 直接导入到系统中生成对应的收货单或是出货单.后端创建收货端和出货单的接口已经有现成的webservice或是标准的xml:这类需要做的就是把客户提供不同种类的Excel ...
- Qt发送一次信号触发两次槽函数的原因
在手动为控件编写槽函数的时候,如果将槽函数名字按如下格式编辑,则不需要再次进行手动关联 void on_pushButton_1_clicked(); void on_radioButton_clic ...
- L8梯度消失、梯度爆炸
houseprices数据下载: 链接:https://pan.baidu.com/s/1-szkkAALzzJJmCLlJ1aXGQ 提取码:9n9k 梯度消失.梯度爆炸以及Kaggle房价预测 代 ...
- 快速搭建网站信息库(小型Zoomeye)
前言:本来是不想重复造车轮的,网上资料有开源的fofa,和一些设计.有的架设太复杂了,好用东西不会用,整个毛线.还有的没有完整代码. 设计方案: 测试平台:windows 测试环境:php ...
- DataTable 与XML 交互
一.将DataTable的内容写入到XML文件中 /// <summary> /// 将DataTable的内容写入到XML文件中 /// </summary> /// < ...
- Java的数组索引问题
/* 数组操作的两个常见小问题: ArrayIndexOutOfBoundsException:数组索引越界异常 原因:你访问了不存在的索引. NullPointerException:空指针异常 原 ...
- pytorch实现手动线性回归
import torch import matplotlib.pyplot as plt learning_rate = 0.1 #准备数据 #y = 3x +0.8 x = torch.randn( ...
- Redis学习与应用-位图
什么是位图 位图bitmap是通过一个bit来表示某个元素对应的值或者状态,是由一组bit位组成,每个bit位对应0和1两个状态,虽然内部还是采用string类型进行存储,但是redis提供了直接操作 ...