标签:
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 }
标签:
原文地址:http://www.cnblogs.com/Tunix/p/4592584.html