zoukankan      html  css  js  c++  java
  • 【UOJ Round #3】

    枚举/二分


      C题太神窝看不懂……

    核聚变反应强度

      QwQ很容易发现次小的公约数一定是gcd的一个约数,然后……我就傻逼地去每次算出a[1],a[i]的gcd,然后枚举约数……这复杂度……哦呵呵。。。

      正解是先找到a[1]的所有质因数啊……然后在刚刚那个算法的“枚举gcd的约数”的时候直接枚举这些质因数就好了……

     1 //UOJ Round3 A
     2 #include<vector>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<iostream>
     7 #include<algorithm>
     8 #define rep(i,n) for(int i=0;i<n;++i)
     9 #define F(i,j,n) for(int i=j;i<=n;++i)
    10 #define D(i,j,n) for(int i=j;i>=n;--i)
    11 using namespace std;
    12 typedef long long LL;
    13 inline LL getint(){
    14     LL r=1,v=0; char ch=getchar();
    15     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
    16     for(; isdigit(ch);ch=getchar()) v=(v<<3)+(v<<1)-'0'+ch;
    17     return r*v;
    18 }
    19 const int N=1e6+10;
    20 /*******************template********************/
    21 
    22 int n,tot,cnt;
    23 LL a[N],b[N],prime[N];
    24 bool vis[N];
    25 inline LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
    26 int main(){
    27 #ifndef ONLINE_JUDGE
    28     freopen("A.in","r",stdin);
    29     freopen("A.out","w",stdout);
    30 #endif 
    31     n=getint();
    32     F(i,1,n) a[i]=getint();
    33     for(LL i=2;i*i<=a[1];i++)
    34         if (!vis[i]){
    35             prime[++tot]=i;
    36             for(LL j=i+i;j*j<=a[1];j+=i) vis[j]=1;
    37         }
    38     F(i,1,tot) if (a[1]%prime[i]==0) b[++cnt]=prime[i];
    39     LL tmp;
    40     F(i,1,n){
    41         tmp=gcd(a[1],a[i]);
    42         if (tmp==1) {printf("-1 "); continue;}
    43         bool sign=1;
    44         F(j,1,cnt)
    45             if (tmp%b[j]==0){
    46                 printf("%lld ",tmp/b[j]);
    47                 sign=0;
    48                 break;
    49             }
    50         if (sign) printf("1 ");
    51     }
    52     return 0;
    53 }
    View Code

    铀仓库

      题解好神啊……如果要直接计算T时间以内能搬几个箱子,那么我们需要枚举s,然后再算每个s在T时间内能搬多少。

      一看就感觉要爆呀。。。

      解决方法是二分= =将最优性问题转化成判定性问题,现在我们的问题就是:给定一个箱子数量K,问最短的时间是多少。

      这样的话我们仍旧可以枚举s,但是由于箱子数是固定的,所以我们根据s-1的答案可以比较方便地得到s的答案。

      

      实现细节方面:我们在放弃左端点箱子而去搬右端点箱子的时候,需要维护一下是哪边先归零……然而我写分类讨论写了好长啊……而@delayyy神犇很简短的就处理完了……事实上我好像想多了……并不需要分类讨论……只要每次取最小值?。。。就可以了……

     1 //UOJ Round3 B
     2 //orz delayyy
     3 #include<vector>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<iostream>
     8 #include<algorithm>
     9 #define rep(i,n) for(int i=0;i<n;++i)
    10 #define F(i,j,n) for(int i=j;i<=n;++i)
    11 #define D(i,j,n) for(int i=j;i>=n;--i)
    12 using namespace std;
    13 typedef long long LL;
    14 inline int getint(){
    15     int r=1,v=0; char ch=getchar();
    16     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
    17     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
    18     return r*v;
    19 }
    20 const int N=5e5+10;
    21 /*******************template********************/
    22 
    23 int n,a[N],x[N],use[N];
    24 LL t,s[N];
    25 inline LL d(int i,int j){return x[j]-x[i];}
    26 inline LL sum(int l,int lc,int r,int rc){
    27     return l==r ? rc-lc : s[r-1]-s[l]+a[l]-lc+rc;
    28 }
    29 bool check(LL K){
    30     int l=1,lc=0,r=n+1,rc=0;
    31 
    32     LL cur=0,sa=0;
    33     F(i,1,n){
    34         if (sa+a[i]<=K) sa+=a[i],cur+=d(1,i)*a[i];
    35         else {r=i,rc=K-sa,cur+=d(1,i)*rc; break;}
    36     }
    37     if (cur<=t) return 1;
    38 
    39     F(i,2,n){
    40         cur+=d(i-1,i)*(sum(l,lc,i,0)-sum(i,0,r,rc));
    41         while(r<=n && d(l,i)>d(i,r)){
    42             int z=min(a[l]-lc,a[r]-rc);
    43             cur+=(d(i,r)-d(l,i))*z;
    44             if (lc+=z,lc>=a[l]) ++l,lc=0;
    45             if (rc+=z,rc>=a[r]) ++r,rc=0;
    46         }
    47         if (cur<=t) return 1;
    48     }
    49     return 0;
    50 }
    51 int main(){
    52 #ifndef ONLINE_JUDGE
    53     freopen("B.in","r",stdin);
    54     freopen("B.out","w",stdout);
    55 #endif 
    56     n=getint(); scanf("%lld",&t); t/=2;
    57     F(i,1,n) x[i]=getint();
    58     F(i,1,n) a[i]=getint(),s[i]=s[i-1]+a[i];
    59 
    60     LL L=1,R=s[n],mid,ans=0;
    61     while(L<=R){
    62         mid=L+R>>1;
    63         if (check(mid)) ans=mid,L=mid+1;
    64         else R=mid-1;
    65     }
    66     printf("%lld
    ",ans);
    67     return 0;
    68 }
    View Code
  • 相关阅读:
    C#泛型类的简单创建与使用
    线程、委托、lambda运算符的简单示例
    异步编程中使用帮助类来实现Thread.Start()的示例
    C#操作INI配置文件示例
    C#“简单加密文本器”的实现
    Java设计模式之模板模式(Template )
    java提取出一个字符串里面的Double类型数字
    阿里云服务器配置SSL证书成功开启Https(记录趟过的各种坑)
    Gson解决字段为空是报错的问题
    shiro 单点登录原理 实例
  • 原文地址:https://www.cnblogs.com/Tunix/p/4592584.html
Copyright © 2011-2022 走看看