【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\n",ans);
67     return 0;
68 }
View Code

 

posted @ 2015-06-21 22:37  Tunix  阅读(252)  评论(0编辑  收藏  举报