• 2019西安多校联训 Day3


    试题链接:http://www.accoders.com/contest.php?cid=1895    考试密码请私信;

    特别鸣谢:zkc奆佬帮助我优化本篇题解(语言表达方面)

       T1

      显然二分求解的一道题,难度中等,但是会被疯狂卡精度

    非常恶心,非常毒瘤

      思路:输入时维护一个前缀和数组,然后分别从前,后方向遍历,找最大最小值

    ,同时记录L,R,二分x,check函数中另起一个数组算一下'-x'后的数组然后,还是

    从前后遍历,找最大最小值,记录l,r,最后判断L和R的大小是不是也符合l,r的大小

    (就是L<R&&l<r||L>R&&l>r),然后疯狂卡精度即可

    T1-
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int a[200010];
     4 double b[200010];
     5 double c[200010];
     6 double maxx,ans,tans,x,num;
     7 int n,L,R=n+1,bigg=-99999,small=10000;
     8 inline bool check(double x){
     9     double maxx=-99999,minn=10000;int l=0,r=n+1;
    10     for(register int i=1;i<=n;i++){
    11         if(L<R) c[i]=b[i]-x*(i*1.0);
    12         else c[i]=b[i]+x*(i*1.0);
    13     }
    14     for(register int i=n;i>=0;i--) if(maxx<c[i]) maxx=c[i],r=i;
    15     for(register int i=1;i<=n;i++) if(minn>c[i]) minn=c[i],l=i;
    16     ans=maxx-minn;
    17     if((l<r&&L<R)||(l>r&&L>R)) return true;
    18     else return false;
    19 }
    20 double ef(double l,double r){
    21     double mid=(l+r)/(2.0);
    22     if(r-l<0.00000000001) return mid;
    23     if(check(mid)) return ef(mid,r);
    24     else return ef(l,mid);
    25 }
    26 int main(){
    27     scanf("%d",&n);
    28     for(register int i=1;i<=n;i++){scanf("%d",&a[i]);b[i]=b[i-1]+a[i];}
    29     for(register int i=n;i>=0;i--) if(bigg<b[i]) bigg=b[i],R=i;
    30     for(register int i=1;i<=n;i++) if(small>b[i]) small=b[i],L=i;
    31     double qwq=ef(0,20000);
    32     check(qwq);
    33     if(ans>499&&ans<500) ans-=0.000001;
    34     printf("%.6lf",ans);
    35     return 0;
    36 }
    Weakness

       T2

      显然的宽搜啊~~~ boom 时间超限,但其实难度中等偏下

    所以是二分宽搜/二分深搜....(这谁想得到啊!!!!)QAQ

    还有一点我用的是宽搜 742ms,而zkc奆佬用的是深搜 255ms QAQ!

      思路:二分找到最小的伤害值,每次二分一个最大的伤害值搜索跑图,高于伤害值的点都不去走

    若能走到最后一排则符合二分向下,否则二分向上,最后找到的就是最小的最大伤害值

    T2-
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int a[1010][1010];
     4 int fx[4]={1,0,-1,0},fy[4]={0,1,0,-1};
     5 int x,y,ans,n,m,maxx;
     6 queue <int> q;
     7 bool vis[1010][1010];
     8 bool check(int qwq){
     9     while(!q.empty()) q.pop();
    10     for(register int i=1;i<=m;i++)q.push(1),q.push(i),vis[1][i]=1;
    11     while(!q.empty()){
    12         x=q.front();q.pop();
    13         y=q.front();q.pop();
    14         if(x==n) return true;
    15         for(register int i=0;i<4;i++){
    16             int px=x+fx[i];
    17             int py=y+fy[i];
    18             if(px<1||px>n||py<1||py>m||a[px][py]>qwq||vis[px][py]) continue;
    19             q.push(px);
    20             q.push(py);
    21             vis[px][py]=1;
    22         }
    23     }
    24     return false;
    25 }
    26 int ef(int l,int r){
    27     //cout<<l<<" "<<r<<endl;
    28     if(l==r) return l;
    29     int mid=(l+r)>>1;
    30     memset(vis,false,sizeof(vis));
    31     if(check(mid)) ef(l,mid);
    32     else ef(mid+1,r);
    33 }
    34 int main(){
    35     scanf("%d%d",&n,&m);
    36     for(register int i=1;i<=n;i++)
    37     for(register int j=1;j<=m;j++){scanf("%d",&a[i][j]);maxx=max(maxx,a[i][j]);}
    38     printf("%d",ef(0,1000));
    39     return 0;
    40 }
    飓风营救

       T3

      显然打表啊!打表出奇迹!打表nb!难度中等

    打表时间复杂度O(285年) 算了吧....

      思路:其实这题跟数论也有点关系,首先先打个素数表,众所周知,素数*素数的得数必然有两个约数

    前提是两个素数不等,假设是两个相同素数相乘每乘一次显然约数个数=(i+1)

      举例:

      2 约数=2

      2*2 约数=3

      2*2*2 约数=4

      那搜索方式就是从最大的素数往下搜索,如果乘上当前素数没爆,接着乘

    爆了就往回走,无路可走时显然就结束了

    T3-
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int p[26]={1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,101};
     4 int primenum;
     5 bool ac;
     6 long long ans,tans;
     7 long long n;
     8 void dfs(long long now,long long num,long long deep,long long last){
     9     if(deep>=26) return;
    10     else{ 
    11         if(num>ans){tans=now,ans=num;}
    12         else if(num==ans) tans=min(tans,now);
    13         for(register int i=1;i<=last;i++){
    14             if(now*p[deep]<=n){
    15                 now*=p[deep];
    16                 dfs(now,num*(i+1),deep+1,i);
    17             }
    18             else break;
    19         }
    20     }
    21 }
    22 int main(){
    23     scanf("%lld",&n);
    24     dfs(1,1,0,26);
    25     printf("%lld",tans);
    26     return 0;
    27 }
    最多约数

      end;

      

      

  • 相关阅读:
    ACdream 1114(莫比乌斯反演)
    ACdream 1148(莫比乌斯反演+分块)
    bzoj2301(莫比乌斯反演+分块)
    hdu1695(莫比乌斯反演)
    hdu4908(中位数)
    bzoj1497(最小割)
    hdu3605(最大流+状态压缩)
    【Leetcode】Add Two Numbers
    【Leetcode】Add Binary
    【Leetcode】Single Number II
  • 原文地址:https://www.cnblogs.com/liuhailin/p/11010555.html
Copyright © 2020-2023  润新知