• 【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
    ",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("
    ");
    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
    ",f[mx]);
    41     }
    42     return 0;
    43 }
    D2 T3

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

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

  • 相关阅读:
    使用Hugo框架搭建博客的过程
    使用Hugo框架搭建博客的过程
    使用Hugo框架搭建博客的过程
    Windows软件包管理工具:Scoop
    Centos8 安装ifconfig(net-tools.x86_64)
    Centos8 重启网卡方法
    使用Visual Studio 2019--调试汇编32位代码的详细步骤
    linux 三剑客之awk总结
    linux 三剑客之sed常用总结
    mysql数据库的笔记
  • 原文地址:https://www.cnblogs.com/JKAI/p/7791493.html
Copyright © 2020-2023  润新知