【NOIP2016】提高组

Day1

T1玩具谜题

题目链接

简单模拟题,注意一下取余啊方向啊什么的就行了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 const int M=1e5+10;
 5 using namespace std;
 6 struct point{
 7     int fa;
 8     char ch[12];
 9 }e[M];
10 int main()
11 {
12     int n,m,tu,k,now=0;
13     scanf("%d %d",&n,&m);
14     for(int i=0;i<=n-1;i++)
15         scanf("%d %s",&e[i].fa,e[i].ch);
16     for(int i=1;i<=m;i++){
17         scanf("%d %d",&tu,&k);
18         if((!e[now].fa&&!tu)||(e[now].fa&&tu))now=(now-k+n)%n;
19         else now=(now+k)%n;
20     }
21     printf("%s",e[now].ch);
22     return 0;
23 }

D1 T1

T2天天爱跑步

神题,当然得写独立的题解-->戳这里

T3换教室

期望dp,也有独立题解-->戳这里



Day2

T1组合数问题

题目链接

预处理杨辉三角(顺便取模),再用另一个三角s[x][y]表示0 <= i <= n, 0 <= j <= min(i, m)里C(i,j)为0的数量-->类似前缀和。

然后就可以O(1)查询啦!

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 int t,k,n,m,c[2002][2002],s[2002][2002];
 7 int read()
 8 {
 9     int ans=0,f=1;char c=getchar();
10     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
11     while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-48;c=getchar();}
12     return ans*f;
13 }
14 int main()
15 {
16     t=read();k=read();
17     c[0][0]=1;
18     for(int i=1;i<=2000;i++)
19     {
20         c[i][0]=1;
21         for(int j=1;j<=i;j++)
22         {
23             c[i][j]=(c[i-1][j-1]+c[i-1][j])%k;
24         }
25     }
26     s[0][0]=0;
27     for(int i=1;i<=2000;i++)
28     {
29         s[i][0]=0;
30         for(int j=1;j<i;j++)
31         {
32             s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1];
33             if(c[i][j]==0)s[i][j]++;
34         }
35         s[i][i]=s[i][i-1];if(!c[i][i])s[i][i]++;
36     }
37     for(int i=1;i<=t;i++)
38     {
39         scanf("%d %d",&n,&m);
40         printf("%d\n",s[n][min(n,m)]);
41     }
42     return 0;
43 }

D2 T1

T2蚯蚓

题目链接

这道题用STL的优先队列只能拿65分......

仔细想想会发现,每次截出的两条蚯蚓,如果我们把较大的和较小的分别放进两个队列里,就会发现满足递减性质!

这样就省去了排序->v->

每次从原队列和另外两个队列里取出最长的一条执行操作就好了。

但要注意精度的问题-->不要像我一样自作聪明地把u提前变成v-u-->这样会有±1的误差。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 typedef double Cu;
 5 const int N=1e5+10,M=7e6+10;
 6 int read(){
 7     int ans=0,f=1;char c=getchar();
 8     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
 9     while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-48;c=getchar();}
10     return ans*f;
11 }
12 int max(int x,int y){return x>y?x:y;}
13 int min(int x,int y){return x<y?x:y;}
14 int n,m,q,u,v,t,a[N],mul[3][M];
15 int q1[M],q2[M],ans[M];
16 int h1=1,t1=0,h2=1,t2=0,h=1;
17 void get_rank(){
18     int rank=1,sum=0;
19     while(rank<=n+m&&sum<(n+m)/t){
20         bool kk=rank%t;
21         int mx=h<=n?a[h]+mul[0][h]:0,mx1=h1<=t1?q1[h1]+mul[1][h1]:0,mx2=h2<=t2?q2[h2]+mul[2][h2]:0;
22         mx=max(mx,max(mx1,mx2));
23         if(!kk)printf("%d ",mx),sum++;
24         if(h<=n&&mx==a[h]+mul[0][h])mul[0][h+1]+=mul[0][h],h++;
25         else if(h1<=t1&&mx==mx1)mul[1][h1+1]+=mul[1][h1],h1++;
26         else mul[2][h2+1]+=mul[2][h2],h2++;
27         rank++;
28     }
29 }
30 bool cmp(int x,int y){return x>y;}
31 int get_p(int x){
32     return (long long)x*u*1.0/v;
33 }
34 int main(){
35     n=read();m=read();q=read();u=read();v=read();t=read();
36     Cu p=u*1.0/v;
37     for(int i=1;i<=n;i++)a[i]=read();
38     std::sort(a+1,a+1+n,cmp);
39     for(int i=1;i<=m;i++){
40         int mx=h<=n?a[h]+mul[0][h]:0,mx1=h1<=t1?q1[h1]+mul[1][h1]:0,mx2=h2<=t2?q2[h2]+mul[2][h2]:0;
41         mx=max(mx,max(mx1,mx2));
42         ans[i]=mx;
43         if(h<=n&&mx==a[h]+mul[0][h])mul[0][h+1]+=mul[0][h],h++;
44         else if(h1<=t1&&mx==mx1)mul[1][h1+1]+=mul[1][h1],h1++;
45         else mul[2][h2+1]+=mul[2][h2],h2++;
46         if(h<=n)mul[0][h]+=q;
47         mul[1][h1]+=q;mul[1][++t1]-=q;
48         mul[2][h2]+=q;mul[2][++t2]-=q;
49         int small=get_p(mx);int big=mx-small;
50         if(small>big)std::swap(small,big);
51         q1[t1]=big;
52         q2[t2]=small;
53     }
54     for(int i=1;i<=m/t;i++)printf("%d ",ans[i*t]);
55     printf("\n");
56     get_rank();
57     return 0;
58 }

D2 T2

T3愤怒的小鸟

题目链接

可以剪枝DFS,当然这个数据范围很明显就是状压DP。

g[i][j]表示选择了i,j这两个点作为一条抛物线可以经过的猪的状态-->01状态;

那么预处理就是O(n3)的。状态转移方程:

f[s|g[i][j]]=min(f[s|g[i][j]],f[s]+1);

其中s为当前状态,这样的话总复杂度是O(n3+n2*2n)。

最后就是注意一下判断三点是否在一条抛物线上的精度问题和抛物线必须满足a<0

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define mem(a,p) memset(a,p,sizeof(a))
 5 typedef double Cu;
 6 const Cu eps=1e-10;
 7 Cu xi[20],yi[20];
 8 int f[1<<19],g[20][20];
 9 int min(int x,int y){return x<y?x:y;}
10 Cu abs(Cu x){return x>0?x:-x;}
11 int main(){
12     int tt,n,m;
13     scanf("%d",&tt);
14     while(tt--){
15         scanf("%d %d",&n,&m);
16         int mx=(1<<n)-1;f[0]=0;
17         for(int i=1;i<=mx;i++)f[i]=25;
18         for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)g[i][j]=0;
19         for(int i=1;i<=n;i++)scanf("%lf %lf",&xi[i],&yi[i]),f[1<<(i-1)]=1;
20         for(int i=1;i<=n;i++)
21             for(int j=i;j<=n;j++)
22                 if(i==j)g[i][i]=1<<(i-1);
23                 else{
24                     if(xi[i]==xi[j]||abs(xi[j]*yi[i]-yi[j]*xi[i])<eps)continue;
25                     Cu a=(xi[j]*yi[i]-xi[i]*yi[j])/(xi[i]*xi[j]*(xi[i]-xi[j]));
26                     Cu b=(yi[i]-xi[i]*xi[i]*a)/xi[i];
27                     if(a>=0)continue;
28                     int now=(1<<(i-1))+(1<<(j-1));
29                     g[i][j]=now;
30                     for(int k=1;k<=n;k++){
31                         if(k==i||k==j)continue;
32                         if(abs(a*xi[k]*xi[k]+b*xi[k]-yi[k])<=eps)g[i][j]|=1<<(k-1);
33                     }
34                 }
35         for(int s=0;s<=mx;s++){
36             for(int i=1;i<=n;i++)
37                 for(int j=i;j<=n;j++)
38                 f[s|g[i][j]]=min(f[s|g[i][j]],f[s]+1);
39         }
40         printf("%d\n",f[mx]);
41     }
42     return 0;
43 }

D2 T3



NOIP提高组系列就终于完结辣(撒花~~)

希望还能有机会补今年的题=)

时间: 2024-10-19 23:50:04

【NOIP2016】提高组的相关文章

【NOIP2016提高组】愤怒的小鸟(状压宽搜)

题目描述 Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如的曲线,其中a,b是Kiana指定的参数,且必须满足a<0. 当小鸟落回地面(即x轴)时,它就会瞬间消失. 在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi). 如果某只小鸟的飞行轨迹经过了(xi,yi),那么第i只小猪就会被消灭掉,同时小鸟将会沿着原先

noip2016——提高组——蚯蚓

大概这题难度提高+省选-. 我也做了半天. 这题如果用优先队列做的话会时间超限. 所以就要用另一种巧妙的做法. 见代码-- 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int read(){ 6 int t=1,num=0;char c=getchar(); 7 while(c>'9'||c<'0'){if(c=='-')t=-1

[NOIP2016提高组]组合数问题

题目:UOJ#263.洛谷P2822.Vijos P2006.codevs5947. 题目大意:t组数据,每次给你n和m$\leq 2000$,求对于所有的$(0\leq i\leq n)$,$(0\leq j\leq m)$的(i,j),有多少对满足$C^j_i\equiv 0(mod\ k)$. 解题思路:此题是一道数论题.首先,组合数有一个递推公式:$C^m_n=C^m_{n-1}+C^{m-1}_n$,这其实和杨辉三角的递推公式是一样的.那么我们可以预处理出所有的组合数,然后对于每一个问

JZOJ 4639 Angel Beats!【NOIP2016提高组A组7.16】

Angel Beats! (这是一部日漫,7.16的出题人好神奇,名字都来自于影音作品) 题目大意 给你一棵1为根的树,然后会有q个询问,向你查询点x子树和点y子树的重心,重心可能会有很多个,你只需要输出距离和即可. 两棵子树的重心的定义如下:在树上找到一个点,使得该点到两棵子树中所有点距离之和最小,即这两棵子树的重心. 输入格式 第一行一个整数 ,代表点的数量. 接下来 n-1行,第i 行的表示节点i 的父亲节点. 接下来一个整数q ,为询问的个数. 接下来q 行,每行两个数x,y ,表示查询

JZOJ 4638 第三条跑道 【NOIP2016提高组A组7.16】

第三条跑道 该题目的名字是一首歌 题目大意 输入格式 输出格式 对于每个询问,单独一行输出答案. 样例输入 5 2 3 4 5 6 3 1 1 5 0 2 3 6 1 2 3 样例输出 32 48 数据范围 题解 我们先看一下φ的通式. 其中p1, p2--pn为x的所有质因数,x是不为0的整数. 再看一下数据范围,,这也就意味着ai在任何时刻都满足它的素因子是600以内的,而φ(ai)只跟它的素因子有关. 因为是区间查询/修改,当然是开线段树了. 600以内的素因子有109个,所以我们就种10

洛谷 P1850 换教室(NOIp2016提高组D1T3)

题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 2n2n 节课程安排在 nn 个时间段上.在第 ii(1 \leq i \leq n1≤i≤n)个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室 c_ic?i?? 上课,而另一节课程在教室 d_id?i?? 进行. 在不提交任何申请的情况下,学生们需要按时间段的顺序依次完成所有的 nn 节安排好的课程.如果学生想更换第 ii 节课程的教室,则需要提出申请.

洛谷 P2827 蚯蚓(NOIp2016提高组D2T2)

题目描述 本题中,我们将用符号?c?表示对c向下取整,例如:?3.0?=?3.1?=?3.9?=3. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n)a?i??(i=1,2,...,n),并保证所有的长度都是非负整数(即:可能存在长度为0的蚯蚓). 每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两

[NOIP2016提高组]愤怒的小鸟

题目:UOJ#265.洛谷P2831.Vijos P2008. 题目大意:有n头猪,都在一个二维坐标系里(每头猪坐标为两位小数).规定每只鸟能从(0,0)处发射,且经过的抛物线一定为$y=ax^2+bx$,且$a<0$. 如果几头猪头猪在同一条抛物线上,那么它就能被一只鸟打死.问至少发射多少只鸟才能打死所有的猪? 解题思路:由于n最大才18,我们可以用二进制的每一个位来保存一只鸟,做一个状压DP. 那么就是判断抛物线的事了.我们枚举两头猪,算出a和b的值.由于鸟从原点飞出,我们直接套公式计算即可

【NOIP2016提高组】换教室

https://www.luogu.org/problem/show?pid=1850 题面很长,实质很水的一道期望DP题.题面自带劝退效果. 首先用Floyd算出任意两点的最短路径.然后设f(i,j,0)为前i节课申请更换j节,且不申请第i节时的最小期望:设f(i,j,1)前i节课申请更换j节,且申请第i节时的最小期望.可得下面这个超长的状转方程:f(i,j,0)=min{ f(i-1,j,0) + dist(c[i-1],c[i]),    // 不申请第i-1节 f(i-1,j,1) +

[NOIP2016提高组]换教室

题目:洛谷P1850.UOJ#262.BZOJ4720.Vijos P2005. 题目大意:有n个时间段,第i个时间段只能在教室$c_i$上课,另一个上这门课的教室在$d_i$.现在你最多可以进行m次申请,对于第i个时间段的申请如果成功,那么就能在$d_i$教室上课,但成功率为$p_i$.且教室与教室之间用e条双向道路连接,每条路有一个耗费体力的值.问申请哪几门课程可以使因在教室间移动耗费的体力值的总和的期望值最小. 解题思路:这是一道期望dp问题.对于每一时间段(第一时间段除外),我们可以分为