zoukankan      html  css  js  c++  java
  • 【NOIP模拟赛】总结

    题目描述

    输入

    第一行是5个正整数,n,m,k,S,T,分别代表无向图点数,边数,蝙蝠的数量,二小姐所在起点的编号,目标点的编号。
    第二行是k个正整数,分别代表大小姐每个蝙蝠所在的起点的编号。接下来有m行,每行有4个正整数,u,v,q,p,分别是该边的起点、终点,蝙蝠通过该
    路花费的代价,二小姐通过该路花费的代价。

    输出

    一行,一个整数,所有人物达到终点所需要的代价的和的最小值。

    样例输入

    5 5 2 3 4 1 5 1 2 3 5 3 2 3 5 2 4 4 9 3 4 9 6 5 4 1 1

    样例输出

    13

    提示

    1号蝙蝠从1到2,花费3

    二小姐从3到2,花费5,遇见蝙蝠,之后不计算费用1号蝙蝠从2到4,花费4

    2号蝙蝠从5到4,花费1

    总计13
     
    其中30%:n<=200。另有20%:保证S=T。

    另有20%:保证k<=5,n<=1000,m<=10000。100%:n<=10000,m<=100000,k<=10000,1<=S、T、u、v<=n,1<=p、q<=1000,不保证

    蝙蝠起点互不相等,数据中可能有重边和自环,保证所有点均能走到T点(即不存在无解情况)。
     
    题解:
    很容易想到枚举每一个个点作为蝙蝠和二小姐的交点
    但是时间内存不允许,于是我们优化,我们可以虚拟一个S' S'到每一个蝙蝠的起点有一条,长度为 -dist ki-T
    然后答案就是sum(F[ki][T])+min(F[s'][i]+F[S][i]+F[i][T])
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=10005,M=100005,INF=1999999999,MOD=100050;
     7 int head[N],num=0;
     8 struct Lin{
     9     int next,to,dis[2];
    10 }a[M<<1];
    11 void init(int x,int y,int z1,int z2){
    12     a[++num].next=head[x];a[num].to=y;a[num].dis[0]=z1;a[num].dis[1]=z2;head[x]=num;
    13     if(!x)return ;a[++num].next=head[y];a[num].to=x;a[num].dis[0]=z1;a[num].dis[1]=z2;head[y]=num;
    14 }
    15 int gi(){
    16     int str=0;char ch=getchar();
    17     while(ch>'9' || ch<'0')ch=getchar();
    18     while(ch>='0' && ch<='9')str=str*10+ch-48,ch=getchar();
    19     return str;
    20 }
    21 int n,m,k,S,T;int f[5][N],q[N*10],s[N];bool vis[N];
    22 void spfa(int sta,bool tt)
    23 {
    24     for(int i=1;i<=n;i++)vis[i]=false,f[sta][i]=INF;
    25     int t=0,sum=1,x,u;
    26     int from=0;
    27     if(sta==1)from=S;if(sta==2)from=T;if(sta==3)from=0;
    28     q[1]=from;vis[from]=true;f[sta][from]=0;
    29     while(t!=sum)
    30     {
    31         t++;t%=MOD;
    32         x=q[t];
    33         for(int i=head[x];i;i=a[i].next)
    34         {
    35             u=a[i].to;
    36             if(a[i].dis[tt]+f[sta][x]<f[sta][u])
    37             { 
    38                 f[sta][u]=f[sta][x]+a[i].dis[tt];
    39                 if(!vis[u])vis[u]=true,sum++,sum%=MOD,q[sum]=u;
    40             }
    41         }
    42         vis[x]=false;
    43     }
    44 }
    45 int main()
    46 {
    47     n=gi();m=gi();k=gi();S=gi();T=gi();
    48     for(int i=1;i<=k;i++)s[i]=gi();
    49     int x,y,z1,z2;
    50     for(int i=1;i<=m;i++)
    51     {
    52         x=gi();y=gi();z1=gi();z2=gi();
    53         if(x==y)continue;
    54         init(x,y,z1,z2);
    55     }
    56     spfa(1,1);spfa(2,0);
    57     long long sum=0;
    58     for(int i=1;i<=k;i++)init(0,s[i],-f[2][s[i]],0),sum+=f[2][s[i]];
    59     spfa(3,0);
    60     long long ans=INF,tmp;
    61     long long pp=0;
    62     for(int i=1;i<=n;i++)
    63     {
    64         tmp=f[1][i]+f[3][i]+f[2][i];
    65         if(tmp<ans)ans=tmp,pp=i;
    66     }
    67     printf("%lld",ans+sum);
    68     return 0;
    69 }

    题目描述

    输入

    第一行是一个正整数n,表示上式中的p的个数。
     
    接下来有n行,每一行两个正整数pi ei 

    输出

    样例输入

    2 2 2 3 2

    样例输出

    2 2 3 1

    提示

    样例解释

    N=2*2*3*3=36

    phi(N)=36*(1-1/2)*(1-1/3)=12 12=2*2*3

    样例输入二

    4

    37 1

    3 4

    37 1

    333667 2

    样例输出二

    2 4

    3 8

    37 2

    167 1 333667 1


     题解:

    水的数论,分解每一个pi-1即可

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 typedef long long ll;
     8 const int N=500002,M=1000000,T=1000055;
     9 int gi(){
    10     int str=0;char ch=getchar();
    11     while(ch>'9' || ch<'0')ch=getchar();
    12     while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
    13     return str;
    14 }
    15 bool d[M];int mark[T];bool cf[T];
    16 ll qm(ll x,int k)
    17 {
    18     if(x==0)return 0;
    19     if(k==0)return 1;
    20     ll sum=1;
    21     while(k)
    22     {
    23         if(k&1)sum*=x;
    24         k>>=1;x*=x;
    25     }
    26     return sum;
    27 }
    28 int a[T],num=0;int z[N],t=0;
    29 void qd(int p)
    30 {
    31     int lim;int c;
    32     num=0;
    33     for(int i=1;i<=t;i++){if(p%z[i]==0)a[++num]=z[i];}
    34     for(int i=1;i<=num;i++)
    35     {
    36         int k=0,tmp=p;
    37         while(tmp)
    38         {
    39             if(tmp%a[i])break;
    40             k++;tmp/=a[i];
    41         }
    42         mark[a[i]]+=k;
    43     }
    44 }
    45 int main()
    46 {
    47     //freopen("pp.in","r",stdin);
    48     int n,x,y;
    49     scanf("%d",&n);
    50     memset(mark,0,sizeof(mark));
    51     for(int i=1;i<=n;i++)
    52     {
    53         x=gi();y=gi();
    54         mark[x]+=y;
    55         cf[x]=true;
    56     }
    57     int m=1e6;
    58     d[2]=false;
    59     for(int i=2;i<=m;i++)
    60     {
    61         if(d[i])continue;
    62         z[++t]=i;
    63         for(int j=2*i;j<=m;j+=i)d[j]=true;
    64     }
    65     int to=1e6;
    66     for(int i=1;i<=to;i++)
    67     {
    68         if(cf[i])
    69         qd(i-1),mark[i]--;
    70     }
    71     for(int i=1;i<=to;i++)
    72     {
    73         if(mark[i])printf("%d %d
    ",i,mark[i]);
    74     }
    75     return 0;
    76 }

    题目描述

    输入

    第一行一个正整数n,代表积木的个数。 接下来有n行,每行两个数li,ri,分别代表第i块积木左端点和右端点。

    输出

    输出一行两个整数,用一个空格隔开,分别代表最底层最多有多少积木和积木最少有多 少层。

    样例输入

    6 1 2 2 3 4 5 5 6 1 4 3 6

    样例输出

    4 2

    提示


    第 1、2、3、4 块放在最底层,第 5 块第二层,第 6块第三层。此时底层共 4块积木。


    第 1、2、6块放在最底层,第 3、4、5块第二层。此时高度为 2。



    30%:n<=10,0<=l,r<=20

    另 20%: n<=100,0<=l<=50,r=l+2,即每块积木长均为 2

    100%:n<=100000,-2*10^8<=l,r<=2*10^8

    题解:

    贪心,第一问线段覆盖,按右端点排序,然后以此判断 l>=last 满足就加入

    第二问将每一条线段拆成两个点 再将每个点排序,线性扫描一边,遇l h++遇r h-- 意为能塞入底层就塞入

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=100005;
     7 int gi(){
     8     int str=0,f=1;char ch=getchar();
     9     while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    10     while(ch>='0' && ch<='9')str=str*10+ch-48,ch=getchar();
    11     return str*f;
    12 }
    13 struct Point{
    14     int l,r;
    15 }a[N];
    16 bool comp(const Point &p,const Point &q){return p.r<q.r;}
    17 struct Pointed{
    18     int x;bool t;
    19 }p[N<<1];
    20 bool cmp(const Pointed &p,const Pointed &q){if(p.x!=q.x)return p.x<q.x;return p.t>q.t;}
    21 int main()
    22 {
    23     int n=gi();
    24     for(int i=1;i<=n;i++)
    25     {
    26         a[i].l=gi();a[i].r=gi();
    27         p[(i<<1)-1].x=a[i].l;p[(i<<1)-1].t=0;
    28         p[i<<1].x=a[i].r;p[i<<1].t=1;
    29     }
    30     sort(a+1,a+n+1,comp);
    31     int from=-2e9,ans1=0;
    32     for(int i=1;i<=n;i++)
    33     {
    34         if(a[i].l>=from)
    35         {
    36             ans1++;
    37             from=a[i].r;
    38         }
    39     }
    40     printf("%d ",ans1);
    41     sort(p+1,p+(n<<1)+1,cmp);
    42     int top=0,ans2=0,ppap=(n<<1);
    43     for(int i=1;i<=ppap;i++)
    44     {
    45         if(!p[i].t)top++;
    46         else top--;
    47         if(top>ans2)ans2=top;
    48     }
    49     printf("%d",ans2);
    50     return 0;
    51 }

    题目描述

     

    擦弹(graze)

    输入

    第一行是1个正整数n,代表道路长度。
    接下来有4n-4行,每行n个整数,第i行第j个数代表在i时刻(开始为0时刻)在第j格内受到的伤害。

    输出

    两个整数,用空格隔开,分别代表最小的miss数,和在miss数最小的情况下最大的graze 数。

    样例输入

    2 1 2 2 2 3 2 4 2

    样例输出

    30 10

    提示

    只有一种走法。

    第一回合:第一格3分身,第二格1分身,miss5,graze1。

    第二回合:第一格2分身,第二格2分身,miss8,graze2。

    第三回合:第一格1分身,第二格3分身,miss9,graze3。

    第四回合:第一格0分身,第二格4分身,miss8,graze4。


    其中30%数据:n<=3其中50%数据:n<=10其中70%数据:n<=30

    100%数据:n<=100,每时刻每格中弹幕数均为正数且小于  1000
    题解:
    简单的高维dp 注意高维常数 F[i][j][k][g]表示i时刻,第一个分身走的步数为j,第二个为k,第三个为g,第四个为l-i-j-k的最小miss值
    然后以miss为最高优先级,每一次miss更新 graze就更新,miss相等则取较大者
    第一维明显可以滚动掉 注意边界条件
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int N=105,M=455;
     8 int F[2][N][N][N],p[2][N][N][N];int a[N];
     9 int gi(){
    10     int str=0;char ch=getchar();
    11     while(ch>'9' || ch<'0')ch=getchar();
    12     while(ch>='0' && ch<='9')str=str*10+ch-48,ch=getchar();
    13     return str;
    14 }
    15 int main()
    16 {
    17     int n;
    18     scanf("%d",&n);
    19     int m=4*n-4;
    20     int tmp=0,l=0,pc=0;
    21     memset(F,127/3,sizeof(F));
    22     F[0][0][0][0]=0;
    23     int c=0,cc=1;
    24     for(int i=1;i<=m;i++)
    25     {
    26         for(int j=1;j<=n;j++)
    27         {
    28             a[j]=gi();
    29         }
    30         for(int j=0;j<n;j++)
    31         {
    32             if(j>i)break;
    33             for(int k=j;k<n;k++)
    34             {
    35                 if(k+j>i)break;
    36                 pc=k>i-j-k-n?k:i-j-k-n;
    37                 for(int g=pc;g<n;g++)
    38                 {
    39                     if(g+j+k>i)break;
    40                     l=i-j-k-g;
    41                     if(l<g-33)break;
    42                     int *pp=&F[cc][j][k][g];
    43                     int *qq=&p[cc][j][k][g];
    44                     *pp=2e8;
    45                     *qq=0;
    46                     tmp=a[j+1]+a[k+1]+a[g+1]+a[l+1];
    47                     if(tmp+F[c][j-1][k][g]<=*pp&& j)
    48                     {
    49                         int t=F[c][j-1][k][g];
    50                         if(tmp+t<*pp)
    51                         *qq=p[c][j-1][k][g]+a[j];
    52                         else if(p[c][j-1][k][g]+a[j]>*qq)*qq=p[c][j-1][k][g]+a[j];
    53                         *pp=tmp+t;
    54                     }
    55                     if(tmp+F[c][j][k-1][g]<=*pp&& k)
    56                     {
    57                         int t=F[c][j][k-1][g];
    58                         if(tmp+t<*pp)
    59                         *qq=p[c][j][k-1][g]+a[k];
    60                         else if(p[c][j][k-1][g]+a[k]>*qq)*qq=p[c][j][k-1][g]+a[k];
    61                         *pp=tmp+t;
    62                     }
    63                     if(tmp+F[c][j][k][g-1]<=*pp&& g)
    64                     {
    65                        int t=F[c][j][k][g-1];
    66                         if(tmp+t<*pp)
    67                         *qq=p[c][j][k][g-1]+a[g];
    68                         else if(p[c][j][k][g-1]+a[j]>*qq)*qq=p[c][j][k][g-1]+a[g];
    69                         *pp=tmp+t;
    70                     }
    71                     if(tmp+F[c][j][k][g]<=*pp)
    72                     {
    73                         int t=F[c][j][k][g];
    74                         if(tmp+t<*pp)
    75                         *qq=p[c][j][k][g]+a[l];
    76                         else if(p[c][j][k][g]+a[l]>*qq)*qq=p[c][j][k][g]+a[l];
    77                         *pp=tmp+t;
    78                     }
    79                 }
    80             }
    81         }
    82         c^=1;cc^=1;
    83     }
    84     cout<<F[c][n-1][n-1][n-1]<<" "<<p[c][n-1][n-1][n-1];
    85     return 0;
    86 }
  • 相关阅读:
    Hanoi塔
    采药
    进制转换(大数)
    Load Balancing with NGINX 负载均衡算法
    upstream模块实现反向代理的功能
    epoll
    在nginx启动后,如果我们要操作nginx,要怎么做呢 别增加无谓的上下文切换 异步非阻塞的方式来处理请求 worker的个数为cpu的核数 红黑树
    粘性会话 session affinity sticky session requests from the same client to be passed to the same server in a group of servers
    负载均衡 4层协议 7层协议
    A Secure Cookie Protocol 安全cookie协议 配置服务器Cookie
  • 原文地址:https://www.cnblogs.com/Yuzao/p/6972931.html
Copyright © 2011-2022 走看看