[Codeforces #196] Tutorial
Link:
A:
枚举
#include <bits/stdc++.h> using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e5+;
int n,m,dat[MAXN],res=<<; int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++) scanf("%d",&dat[i]);
sort(dat+,dat+m+);
for(int i=;i<=m-n+;i++)
res=min(res,dat[i+n-]-dat[i]);
printf("%d",res);
return ;
}
Problem A
B:
可以发现分母为$max(a*d,b*c)$,分子为$|a*d-b*c|$
#include <bits/stdc++.h> using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef pair<int,int> P;
int a,b,c,d,ta,tb,tc,td,resx,resy;
int GCD(int x,int y){return x%y==?y:GCD(y,x%y);} int main()
{
scanf("%d%d%d%d",&a,&b,&c,&d);
resx=abs(a*d-c*b),resy=max(a*d,c*b);
int gcd=GCD(resx,resy);
printf("%d/%d",resx/gcd,resy/gcd);
return ;
}
Problem B
C:
直接贪心,考虑将空格插入连续的序列中
如果可以不翻倍自然答案就是$m$,否则应当尽可能在前面翻倍来减少增加的分数
能推出翻倍$q$次后的分数为$(2^q-1)*2*k$,这样再加上剩余不翻倍的分数即可
#include <bits/stdc++.h> using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef pair<int,int> P;
const ll MOD=1e9+;
ll n,m,k,res;
ll quick_pow(ll a,ll b)
{
ll ret=;
for(;b;b>>=,a=a*a%MOD)
if(b&) ret=ret*a%MOD;
return ret;
} int main()
{
scanf("%I64d%I64d%I64d",&n,&m,&k);
if(!m||!n) return puts(""),;
ll rst=n-m,num=n/k;
if(rst>=num) res=m;
else res=(quick_pow(,num-rst)-)**k%MOD+(m-(num-rst)*k%MOD);
printf("%I64d",(res+MOD)%MOD);
return ;
}
Problem C
D:
官方题解:
将原树转化成有根树,对于一个点的最远关键点分成两类:
1、在该点的子树中,记最远距离为$MaxDown$
2、在树上的其它部分,记最远距离为$MaxUp$
对于1,明显可以$dfs$通过孩子节点来更新
对于2,又要分为两类来更新:
1、在其兄弟节点的子树中,即$MaxDown_{sibling}+2$
2、不在父亲节点的子树中,即$MaxUp_{father}+1$
其中注意用兄弟节点更新时要先记录最大/次大值来保证$O(1)$更新
不过感觉我的方法更简单啊……
先想想如何求一个点到树上任意点的最远距离
明显是用数的直径来解决的经典问题,可用反证法证明最远点一定是直径的两端
发现将任意点改为特定的关键点后该结论依然成立!
因此只要找到关键点中最远的点对$(a,b)$,对于每个点$v$判断$dist(a,v),dist(b,v)\le d$
#include <bits/stdc++.h> using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e5+;
int head[MAXN],tot;
struct edge{int nxt,to;}e[MAXN<<];
int n,m,d,x,y,p[MAXN],rt1,rt2,d1[MAXN],d2[MAXN],res; void add(int from,int to)
{e[++tot].nxt=head[from];e[tot].to=to;head[from]=tot;}
void dfs(int x,int anc,int *d)
{
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=anc)
d[e[i].to]=d[x]+,dfs(e[i].to,x,d);
} int main()
{
scanf("%d%d%d",&n,&m,&d);
for(int i=;i<=m;i++) scanf("%d",&p[i]);
for(int i=;i<n;i++)
scanf("%d%d",&x,&y),add(x,y),add(y,x); d1[]=;dfs(,,d1);
for(int i=;i<=m;i++) if(d1[p[i]]>d1[rt1]) rt1=p[i];
d1[rt1]=;dfs(rt1,,d1);
for(int i=;i<=m;i++) if(d1[p[i]]>d1[rt2]) rt2=p[i];
d2[rt2]=;dfs(rt2,,d2); for(int i=;i<=n;i++)
if(d1[i]<=d&&d2[i]<=d) res++;
printf("%d",res);
return ;
}
Problem D
虽说第一种解法可能代码量稍大,但分类方法还是很实用的:
将无根树转化成有根树后按照是否在该点的子树中分类
其中兄弟节点对该点的贡献不要忘记统计!我一开始就漏掉了……
E:
发现最优解除了叶子节点和根外,其它节点必然都属于$a$
考虑一个点向当前树插入,其要么接在某个节点后,要么重开一棵树
由于$n$只有8,明显排序预处理后枚举各种组合就好了
其中有一些技巧需要注意:
1、采取从根到叶子的构造更加方便
由于树根确定其叶子节点就已经确定,后面接点时就不用再考虑叶子节点的贡献了
2、不要漏考虑最大点本身就是根的情况,这样答案会减少1
#include <bits/stdc++.h> using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef pair<int,int> P;
ll n,dat[],dvs[],res=1ll<<; void dfs(int k,int sum,int rt)
{
if(k==n+)
{res=min(res,sum+ll(rt>));return;}
if(dvs[k]>) sum++; dfs(k+,sum+dvs[k],rt+);//单独成树
for(int i=;i<k;i++)//连在之前的节点后
if(dat[i]%dat[k]==)
dat[i]/=dat[k],dfs(k+,sum,rt),dat[i]*=dat[k];
} int main()
{
scanf("%I64d",&n);
for(int i=;i<=n;i++) scanf("%I64d",&dat[i]);
sort(dat+,dat+n+,greater<ll>());
for(int i=;i<=n;i++)
{
ll t=dat[i];
for(int j=;1ll*j*j<=dat[i];j++)
while(t%j==) t/=j,dvs[i]++;
if(t>) dvs[i]++;
} dfs(,,);
printf("%I64d",res);
return ;
}
Problem E
[Codeforces #196] Tutorial的更多相关文章
- Codeforces 196 E. Tricky and Cleve Password
\(>Codeforces \space 196\ E. Tricky\ and\ Cleve\ Password<\) 题目大意 : 给出一个有 \(n\) 个结点,\(m\) 条边的连 ...
- [Codeforces #172] Tutorial
Link: Codeforces #172 传送门 A: 一眼看上去分两类就可以了 1.每个矩形只有两条边相交,重合的形状为菱形 2.每个矩形四条边都有相交 对于情况1答案为$h*h/sin(a)$ ...
- [Codeforces #514] Tutorial
Link: Codeforces #514 传送门 很简单的一场比赛打崩了也是菜得令人无话可说…… D: 一眼二分,发现对于固定的半径和点,能包含该点的圆的圆心一定在一个区间内,求出区间判断即可 此题 ...
- [Codeforces #210] Tutorial
Link: Codeforces #210 传送门 A: 贪心,对每个值都取最大值,不会有其他解使答案变优 #include <bits/stdc++.h> using namespace ...
- [Codeforces #174] Tutorial
Link: Codeforces #174 传送门 A: 求原根的个数,有一条性质是原根个数为$\phi(\phi(n))$,多了一个不会证的性质 如果要确定哪些是原根的话还是要枚举,不过对于每个数不 ...
- [Codeforces #190] Tutorial
Link: Codeforces #190 传送门 A: 明显答案为$n+m-1$且能构造出来 #include <bits/stdc++.h> using namespace std; ...
- [Codeforces #211] Tutorial
Link: Codeforces #211 传送门 一套非常简单的题目,但很多细节都是错了一次才能发现啊…… 还是不能养成OJ依赖症,交之前先多想想corner case!!! A: 模拟,要特判0啊 ...
- [Codeforces #192] Tutorial
Link: Codeforces #192 传送门 前两天由于食物中毒现在还要每天挂一天的水 只好晚上回来随便找套题做做找找感觉了o(╯□╰)o A: 看到直接大力模拟了 但有一个更简便的方法,复杂度 ...
- Codeforces 196 C. Paint Tree
分治.选最左上的点分给根.剩下的极角排序后递归 C. Paint Tree time limit per test 2 seconds memory limit per test 256 megaby ...
随机推荐
- Little Mathematics Knowledge 数学小常识
The sum of arithmetic sequence The sum of geometric sequence A special formula : n·n! = (n+1)! - n! ...
- Spring的BeanFactory体系结构(一)
本文使用的代码是: Spring 3.0 接 触Spring也有很长一段时间了.但是,每次都是直接使用Spring直接提供的API,时间久了,自然也会想探索Spring里面的奥秘.今天上 午,整理出了 ...
- LCD实验学习笔记(五):MMU
内存管理分别页表机制和内存分配机制两块. 页表机制就是管理设备真实物理地址与虚拟地址的动态或静态的映射,基于cpu内部的mmu(内存管理单元)进行. CP15(协处理器)的C0(缓存)是一级页表,含4 ...
- Python3 学习第一天总结
一.python介绍 1.python是一门动态解释性的强类型定义语言: 简单解释一下: 定义变量不需要定义类型的为动态语言:典型的有Python和Ruby,反之定义变量需要定义类型的为静态语言:典型 ...
- Python标准库笔记(2) — re模块
re模块提供了一系列功能强大的正则表达式(regular expression)工具,它们允许你快速检查给定字符串是否与给定的模式匹配(match函数), 或者包含这个模式(search函数).正则表 ...
- 安全测试===sqlmap(贰)转载
十二.列举数据 这些参数用于列举出数据库管理系统信息.数据结构和数据内容. 1.一键列举全部数据 参数:--all 使用这一个参数就能列举所有可访问的数据.但不推荐使用,因为这会发送大量请求,把有用和 ...
- linux内核启动分析(3)
主要分析do_basic_setup函数里面的do_initcalls()函数,这个函数用来调用所有编译内核的驱动模块中的初始化函数. static void __init do_initcalls( ...
- C++ STL结构总结
1. 什么是STL 它的全名是stand template library, 标准模板库,主要是将一些结构和算法写成模板,以便能够实现对任意类型的对象都可以操作,而不需要再一次去写一些算法及结构. 它 ...
- C++中delete和delete[]的区别(转)
原文链接:http://www.cnblogs.com/charley_yang/archive/2010/12/08/1899982.html 一直对C++中的delete和delete[]的区别不 ...
- linux命令(24):find命令
1.命令格式: find pathname -options [-print -exec -ok ...] 2.命令功能: 用于在文件树种查找文件,并作出相应的处理 3.命令参数: pathname: ...