【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 }

铀仓库

  题解好神啊……如果要直接计算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 }

时间: 2024-10-21 10:52:09

【UOJ Round #3】的相关文章

【UOJ Round #1】

枚举/DP+排列组合 缩进优化 QAQ我当时一直在想:$min\{ \sum_{i=1}^n (\lfloor\frac{a[i]}{x}\rfloor + a[i] \ mod\ x) \}$ 然而并不会做啊……一点思路也没有……主要是后面那个取模非常难受…… 其实正解有点逆向思维的感觉:$ans=\sum_{i=1}^n a[i] - max\{ \sum_{i=1}^n \lfloor \frac{a[i]}{x}\rfloor *(x-1) \} $ 也就是先将a[i]全部加起来,然后再

【UOJ Round #8】

A 一道不错的题,虽然大家都觉得是水题,然而蒟蒻我想出来的好慢……Orz alpq 发现其实就是一个网格图,每一个大块都是同一颜色……横纵坐标互不干扰…… 1 //UOJ Round #8 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8

UOJ 30 【CF Round #278】Tourists

Tourists UOJ 30 题目大意 \(n\) 个 \(m\) 条边的无向图,每个点有点权 \(w_i\) , \(q\) 次询问,每次修改第 \(a\) 个点的点权为 \(w\) ,或者查询 \(a\) 到 \(b\) 所有路径中,最小的点权 数据范围 \(1 \le n,m,q \le 10^5, 1 \le w_i \le 10^9\) 时空限制 2s,256MB 分析 对于这种在无向图上查询路径信息的题,一般利用圆方树将其转为树上问题 对于一个方点,维护点双中最小的点权,但是如果这

【Codeforces Round 1129】[Alex Lopashev Thanks-Round] (Div. 1)

Codeforces Round 1129 这场模拟比赛做了\(A1\).\(A2\).\(B\).\(C\),\(Div.1\)排名40. \(A\)题是道贪心,可以考虑每一个站点是分开来的,把目的地最小编号的留到最后,所以答案稍微算一下就行了. \(B\)题是道找规律,首先可以很容易地发现只要前面弄个负数的开头,错误算法就会忽略掉这一个值,所以利用这个来构造答案.(最讨厌构造题了)然后推导一番式子就会发现如果我们将第一个值放-1,则 \(\sum_{i=2}^na_i=k+n\), 再更改一

【Codeforces Round 1132】Educational Round 61

Codeforces Round 1132 这场比赛做了\(A\).\(B\).\(C\).\(F\)四题,排名\(89\). \(A\)题\(wa\)了一次,少考虑了一种情况 \(D\)题最后做出来,但被\(hack\)了...被\(hack\)的原因是没有想到答案会超过\(10^{12}\)(毕竟这个时间上的优化也是在最后迫不得已的情况下加的,就没有考虑正确性... Codeforces 1132 C 题意:给一些区间\([l_i,r_i]\),从中删掉两个,求剩下的区间最多能够覆盖的格子数

【UOJ Goodbye Jiawu】

A.新年的巧克力棒 这道题我的做法是:如果有2^k个巧克力那么很好算,所以把给定的数字二进制拆分: 2得到1,4得到3,8得到7...每一个都是前一位的2倍+1 #include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> using namespace std; int main() { int T; scanf(&quo

【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理

题目描述 求一张有向图的强连通生成子图的数目对 $10^9+7$ 取模的结果. 题解 状压dp+容斥原理 设 $f[i]$ 表示点集 $i$ 强连通生成子图的数目,容易想到使用总方案数 $2^{sum[i]}$ 减去不为强连通图的方案数得到强连通图的方案数,其中 $sum[i]$ 表示点集 $i$ 中边的数目. 考虑什么样的图不是强连通图:缩点后入度为0的强连通分量对应的点集不是全集. 枚举这些入度为0的强连通分量对应的点集,由于无法保证只有这些点构成的入度为0的强连通分量,因此需要进一步容斥.

【SCOI Round #1】题解

$3$ 道题是自己 $yy$ 的……不过 $T2$ 可以用原题做法……$T3$ 小撞原题 $bzoj4556$…… T1 这题就是让证明一个结论…… 我们要加一些无向边,使构造出来的“近似树”最少需要 $k$ 种不同的数才能给所有点都标上号. 设在加无向边之前,最长有向链的长度是 $len$,则 $k\lt len$ 的时候答案一定是 $no$,因为你把最长链上所有的数标号就至少需要 $len$ 种不同的数了. 然后我们就会发现答案可能跟最长有向链有关. 推一推就会发现,在 $m≠0$ 的情况下

【Codeforces Round 650】Codeforces #334 (Div. 1)

模拟CF650,ABC三题,RK90 Codeforces 650 A 思路:首先看式子 \(\sqrt{(x_i-x_j)^2+(y_i-y_j)^2}=|x_i-x_j|+|y_i-y_j|\) 的唯一可行的情况是\(x_i=x_j\)或\(y_i=y_j\).(因为两边之和大于第三边 所以就知道怎么做了. 第一种方法:我们维护三个\(map\),分别存行.列.坐标是\(\dots\)的时候已经有多少个节点. 然后就可以边读边算,读到\((x,y)\)这个坐标的时候把\(ans\)变成 \(