noip2016题解汇总
【uoj#260】玩具谜题
传送门
分析
模拟。
int n,m;
int dir[N]; char nam[N][L];
int a[M],s[M];
int now;
int Go(int now,int dir1,int len) {
int dirFin=(dir[now]^dir1);
if (!dirFin) now-=len; else now+=len;
now%=n; if (now<=0) now+=n;
return now;
}
int main(void) {
n=rd(),m=rd();
rep(i,1,n) {
dir[i]=rd();
scanf("%s",nam[i]+1);
}
rep(i,1,m) a[i]=rd(),s[i]=rd();
now=1;
rep(i,1,m)
now=Go(now,a[i],s[i]);
printf("%s\n",nam[now]+1);
}
【uoj#261】天天爱跑步
题意
分析
我们考虑一条路径\((u,v)\)的影响。设\(u,v\)的LCA为\(anc\),每个节点的深度为\(dep\)。
那么,分两种情况讨论:
①当\(i\)在\(u,anc\)上时,路径\((u,v)\)对\(i\)产生影响,当且仅当
\(dep[u]-dep[i]=w[i]\)
参变分离得:\(dep[u]=dep[i]+w[i]\)
②当\(i\)在\(anc,v\)上时,路径\((u,v)\)对\(i\)产生影响,当且仅当
\(dep[u]-dep[anc]+dep[i]-dep[anc]=dep[u]-2*dep[anc]+dep[i]=w[i]\)
参变分离得:\(dep[u]-2*dep[anc]=w[i]-dep[i]\)
由于情况①与情况②类似,所以我们只要解决了情况①,情况②便迎刃而解。
所以我们现在解决情况①。
我们对于每个点\(i\),求出\(p[i]=dep[i]+w[i]\)。
枚举每条路径\((u,v)\),对于满足\(dep[u]=p[i]\)的所有点\(i\),若\(i\)在\((u,anc)\)上,那么答案+1。
这样直接均摊为\(O(n)\)???!!!
mdzz考场上我就栽在这里了。
复杂度是:\(\sum_{i=1}^{路径条数}\lbrace i|p[i]=当前路径的u\rbrace\)
均摊下来并不是\(O(n)\)的,而是\(O(n^2)\)的。
那怎么办?
我们把所有点按照\(p\)从小到大排序。
把路径按照\(dep[u]\)排序。
那么对于两条链,我们每次处理上下两端连续的信息,用two pointer实现。
那么,对于当前的一条路径,我们把\((u,anc)\)上的每个点的点权+1。
然后有多个单点查询点权是多少。
通过树链剖分+树状数组实现。
就这样少了60pt。
【uoj#262】换教室
待补充...
【uoj#263】组合数问题
传送门
http://uoj.ac/problem/263
多组询问,求\(\sum_{i=0}^n\sum_{j=0}^{\min(i,m)}[k|C_i^j],n,m\leq 2000,k\leq 21\)
分析
\(\sum_{i=0}^n\sum_{j=0}^{\min(i,m)}[k|C_i^j]\\=\sum_{i=0}^n\sum_{j=0}^m [k|C_i^j]\\=\sum_{i=0}^n\sum_{j=0}^m [k|{i!\over j!(i-j)!}]\)
记\(can(k,i,j)=[k|{i!\over j!(i-j)!}]\)
我们只要快速预处理出\(can\),再在\(O(n^2)\)内求出前缀和,就可以支持\(O(1)\)查询了。
设\(k\)的分解为\({a_1}^{p_1}{a_2}^{p_2}...{a_m}^{p_m}\),
\([k|x]=\prod_{i=1}^m[{a_i}^{p_i}|x]\)
所以我们把\(k\)分解,先求出\(cnt(k,i)=i的阶乘中素因子k的个数\),然后即可处理处\(can\)的值。
核心代码
int k;
int ret[B],ned[B],tot;
int cnt[N][B];
int can[N][N];
int sum[N][N];
int cas;
int n,m;
void Split(int x) {
for (int i=2; i<=x; i++)
if (x%i==0) {
tot++;
ret[tot]=i;
ned[tot]=1;
x/=i;
while (x%i==0) ned[tot]++,x/=i;
}
}
int Get(int x,int d) {
int siz=0;
while (x>0) {
int t=x/d;
siz+=t;
x=t;
}
return siz;
}
int Check(int n,int m) { // k|C(n,m) ???
rep(b,1,tot) {
int t=cnt[n][b]-cnt[m][b]-cnt[n-m][b];
if (t<ned[b]) return 0;
}
return 1;
}
int main(void) {
cas=rd(),k=rd();
Split(k);
rep(i,1,U_N) {
rep(b,1,tot)
cnt[i][b]=Get(i,ret[b]);
}
rep(i,0,U_N) rep(j,0,i)
if (Check(i,j))
can[i][j]=1;
rep(i,0,U_N) rep(j,0,i) sum[i][j]=can[i][j];
rep(i,1,U_N) sum[0][i]+=sum[0][i-1];
rep(i,1,U_N) sum[i][0]+=sum[i-1][0]; //Get Border
rep(i,1,U_N) {
rep(j,1,U_N)
sum[i][j]+=sum[i][j-1];
}
rep(i,1,U_N) {
rep(j,1,U_N)
sum[i][j]+=sum[i-1][j];
}
rep(tms,1,cas) {
n=rd(),m=rd();
int res=sum[n][m];
printf("%d\n",res);
}
}
【uoj#264】蚯蚓
传送门
分析
开始的时候被跳蚤吓到了...
因为跳蚤一般都是NOI难度的。
实际上被吓到了之后就太紧张了,简单的合并果子都不会做了,就这样又少了40pt。
然后发育畸形的\(m=0\)的蚯蚓导致我的输出也畸形了,又少了15pt。
很直观的想法就是用优先队列优化模拟。用delta记共同增量。
但是很明显会TLE。
发现自己还有一个特性没有使用:每次加入队列的是由原来的数生成的,而且一定会比原来小。
开三个单调队列。
队列1:原长
队列2:\(\lfloor px\rfloor\)队列
队列3:\(x-\lfloor px\rfloor\)队列
为什么单调?因为每次截出来的蚯蚓长度都是递减的。
类似于哈夫曼树的建立啊。
只不过Huffman树是两条单调队列的。
核心代码:优先队列
int n;
int a[N];
int m;
int u,v;
double p;
int q;
int t;
int del;
priority_queue<int> que;
int main(void) {
n=rd();
m=rd(),q=rd(),u=rd(),v=rd();
p=(double)u/v;
t=rd();
rep(i,1,n) a[i]=rd();
rep(i,1,n) que.push(a[i]);
del=0;
rep(tms,1,m) {
int now=que.top();
now+=del;
que.pop();
int a=(floor)(now*p),b=now-a;
del+=q;
que.push(a-del),que.push(b-del);
if (tms%t==0) {
printf("%d",now);
if (tms+t>m) printf("\n");
else printf(" ");
}
}
rep(tms,1,n+m) {
int now=que.top();
now+=del;
que.pop();
if (tms%t==0) {
printf("%d",now);
if (tms+t>n+m) printf("\n");
else printf(" ");
}
}
}
核心代码:单调队列
#include <cstdio>
#include <cstring>
#include <cctype>
#include <climits>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
typedef long long LL;
const int N=131072;
const int M=10000000;
const int MIN=INT_MIN;
int n,m,q,u,v,t;
int a[N];
int del;
struct Queue {
int q[M]; int qh,qt;
Queue(void) {
memset(q,0,sizeof q);
qh=1,qt=0;
}
void Add(int x) {
q[++qt]=x;
}
void Pop(void) {
q[qh++]=0;
}
int Top(void) {
return q[qh];
}
int Empty(void) {
return qh>qt;
}
}q1,q2,q3;
int rd(void) {
int x=0,f=1; char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
int cmp(int a,int b) {
return a>b;
}
Queue *PreChosen(Queue *a,Queue *b,Queue *c) {
int mx=MIN;
if (!(*a).Empty())
mx=max(mx,(*a).Top());
if (!(*b).Empty())
mx=max(mx,(*b).Top());
if (!(*c).Empty())
mx=max(mx,(*c).Top());
if (!(*a).Empty()&&mx==(*a).Top())
return a;
else if (!(*b).Empty()&&mx==(*b).Top())
return b;
else return c;
}
int main(void) {
#ifndef ONLINE_JUDGE
freopen("uoj#264.in","r",stdin);
freopen("uoj#264.out","w",stdout);
#endif
n=rd(),m=rd(),q=rd(),u=rd(),v=rd(),t=rd();
rep(i,1,n) a[i]=rd();
sort(a+1,a+n+1,cmp); rep(i,1,n) q1.Add(a[i]);
rep(i,1,m) {
Queue *now=PreChosen(&q1,&q2,&q3);
int facLen=(*now).Top()+del; (*now).Pop();
if (i%t==0) printf("%d ",facLen);
del+=q; q2.Add((LL)facLen*u/v-del); q3.Add(facLen-(LL)facLen*u/v-del);
}
printf("\n");
rep(i,1,n+m) {
Queue *now=PreChosen(&q1,&q2,&q3);
int facLen=(*now).Top()+del; (*now).Pop();
if (i%t==0) printf("%d ",facLen);
}
printf("\n");
return 0;
}
【uoj#265】愤怒的小鸟
传送门
分析
状压dp。
设\(f[S]\)表示打掉状态为\(j\)的猪的最小小鸟数。
由于所有鸟都要打掉,所以\(S\)中的状态转移为低位填满的。
转移有两种情况:①打掉一只 ②选择当前这只和另外一只打掉
转移方程自行脑补。
考场上由于精度问题少了20pt。
代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
const int N=32;
const int S=1048576;
const double EPS=1e-8;
int cas;
int n,m;
double x[N],y[N];
int full;
int f[S];
inline int rd(void)
{
int x=0,f=1; char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
/*
a * xi * xi + b * xi = yi
a * xj * xj + b * xj = yj
a*(xi^2)*(xj^2) + b*xi*(xj^2) = yi*(xj^2)
a*(xi^2)*(xj^2) + b*(xi^2)*xj = yj*(xi^2)
b( xi*xj^2 - xi^2*xj ) = yi*(xj^2)-yj*(xi^2)
*/
inline int cmp(double a,double b)
{
if (fabs(a-b)<EPS) return 0;
return a<b?-1:1;
}
int Solve(double xi,double yi,double xj,double yj,double &a,double &b)
{
double t=xi*xj*xj-xi*xi*xj; if (!cmp(t,0)) return 0;
b=(yi*xj*xj-yj*xi*xi)/(xi*xj*xj-xi*xi*xj);
a=(yi-xi*b)/(xi*xi);
if (cmp(a,0)>=0) return 0; else return 1;
}
inline int OnLine(double xi,double yi,double a,double b)
{
double t=a*xi*xi+b*xi;
return !cmp(t,yi);
}
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("angrybirds.in","r",stdin);
freopen("angrybirds.out","w",stdout);
#endif
cas=rd();
rep(tms,1,cas)
{
memset(x,0,sizeof x); memset(y,0,sizeof y);
n=rd(),m=rd();
rep(i,1,n) scanf("%lf%lf",x+i,y+i);
full=(1<<n)-1;
fill(f,f+full+1,n+1); f[0]=0;
rep(st,0,full-1) //从低位到高位,第1个空位
{
int bit=1; while (st>>(bit-1)&1) bit++;
f[st|(1<<(bit-1))]=min(f[st|(1<<(bit-1))],f[st]+1);
rep(i,bit+1,n) if (!(st>>(i-1)&1))
{
double a,b; int tag=Solve(x[bit],y[bit],x[i],y[i],a,b); if (!tag) continue;
int nxST=st; rep(j,bit,n) if (OnLine(x[j],y[j],a,b)) nxST|=(1<<(j-1));
f[nxST]=min(f[nxST],f[st]+1);
}
}
printf("%d\n",f[full]);
}
return 0;
}
noip2016题解汇总的更多相关文章
- LeetCode All in One题解汇总(持续更新中...)
突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...
- LeetCode题解汇总(包括剑指Offer和程序员面试金典,持续更新)
LeetCode题解汇总(持续更新,并将逐步迁移到本博客列表中) LeetCode题解分类汇总(包括剑指Offer和程序员面试金典) 剑指Offer 序号 题目 难度 03 数组中重复的数字 简单 0 ...
- 历年NOIP选题题解汇总
联赛前上vijos板刷往年联赛题,使用在线编辑编写代码,祝我rp++. 废话不多说,挑比较有意思的记一下. 题目是按照年份排序的,最早只到了03年. 有些题目因为 我还没写/很早之前写的忘了 所以就没 ...
- Noip2016题解&总结
原文放在我的uoj博客上,既然新开了blog,那就移过来了 玩具谜题(toy) 送分题.没有什么好说的. 直接按照题目的要求模拟即可. 标准的noip式day1T1. #include<cstd ...
- bzoj题解汇总(1017-1020)
bzoj1017: 树形dp. 设\(f[i][j][k]\)表示当前在点\(i\),有\(j\)个用于上层合成,花费金币为\(k\)的最大攻击力. bzoj1018: 一题多解. http://ww ...
- 网络流24(san)题题解汇总
开坑(烂尾预定 1.餐巾计划问题 题解 2.最小路径覆盖问题 题解 3.试题库问题 题解 4.[CTSC1999]家园 题解 5.骑士共存问题 题解 6.最长不下降子序列问题 题解 7.深海机器人问题 ...
- LibreOJ 题解汇总
目录 #1. A + B Problem #2. Hello, World! #3. Copycat #4. Quine #7. Input Test #100. 矩阵乘法 #101. 最大流 #10 ...
- [NOIP补坑计划]NOIP2016 题解&做题心得
感觉16年好难啊QAQ,两天的T2T3是不是都放反了啊…… 场上预计得分:100+80+100+100+65+100=545(省一分数线280) ps:loj没有部分分,部分分见洛咕 题解: D1T1 ...
- CCPC、Petrozavodsk Camp、OpenCup 题解汇总
省赛 \([\text{2021.11.30}]\) 2021 Jilin Collegiate Programming Contest 全部完成. \([\text{2021.12.25}]\) 2 ...
随机推荐
- if else 语句练习
一.if else 语句.
- SpringMVC整合Tiles框架
SpringMVC整合Tiles框架 Tiles组件 tiles-iconfig.xml Tiles是一个JSP布局框架. Tiles框架为创建Web页面提供了一种模板机制,它能将网页的布局和内容分离 ...
- iOS中3种正则表达式的使用与比较
正则表达式在用户注册和登录中应用很广,通过正则表达式可以判断用户输入的数据正确与否. 在iOS4.0以前开发者一般是通过谓词(NSPredicate)和加入正则表达式的第三方库(如:RegexKitL ...
- MyBatis环境搭建
什么是MyBatis: MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架(O object R relatoin M mapping 框架),MyBatis 避免了几 乎所 ...
- MIME协议生成邮件
MIME协议生成一封复杂的邮件 MIME协议是对RFC822文档的升级和补充,用MIME协议能生成一封有文字.图片和附件的复杂邮件.首先要导入activation.jar和mail.jar.Mail. ...
- 【Unity3D游戏开发】Application.systemLanguage无法区分简体中文和繁体中文 (二六)
游戏发布,语言本地化需要繁体中文和简体中文 iOS8版本之前没问题,iOS9上无法正常识别这两种语言 原因是在iOS9上,Unity通过Application.systemLanguage返回的简体中 ...
- Log4j2在WEB项目中配置
最近决定在新WEB项目中使用新的日志系统Log4j2. 官方介绍和学习文档网址为http://logging.apache.org/log4j/2.x/ 首先在WEB项目中引入以下几个jar包: ① ...
- ggplot2 legend图例的修改
ggplot2中的legend包括四个部分: legend.tittle, legend.text, legend.key, legend.backgroud.针对每一部分有四种处理方式: eleme ...
- Django 过滤器 实例
实例1 safe让Html标签以及一些特殊符号(如<)生效,下面以例子说明: # value = '<b>CPT</b>' # 那么输出的时候,CPT就是加粗的,如果不加 ...
- Oracle 怎么让id自增加
--自增长序列 create table test( tid int not null, tname ), tsex ), tbz ) ) --添加主键约束 alter table test add ...