把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF1753E N Machines

题面传送门

首先你发现题面里有一个初始答案不大于\(2\times 10^9\),这表示最终答案不超过\(4\times 10^{18}\),这表明不用写高精,这是好的。

但是这仅仅如此吗?

可以发现乘\(1\)是没有屁用的,因此可以排除,那么剩下的乘号不超过\(\log V\)个。

我们可以直接暴力\(2^{\log V}\)枚举乘号的状态,然后\(O(n)\)算答案,这样可以做到\(O(nV)\)

但是这样还是不够。

我们考虑对于每种权值一样的点,肯定是先动前面的,再动后面的。这样一定更优。因此我们可以对每个颜色枚举要往后放的点的个数。这样就可以算答案了。

这样的形式与\(V\)的约数个数形式很像,可以认为是一样的,复杂度变成\(O(n\sqrt [3]{V})\)

但是还是不能过捏,我们发现我们其实要求的就是前\(k\)大的和,因此可以二分第\(k\)大的值,然后去\(\log V\)个小段里二分,就可以算出答案,因此复杂度变成\(O(\sqrt[3]V\log^2 V\log n+n\log n)\)。就能过了。

code:

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n))
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=1e6+5,M=N*4+5,K=1e5+5,mod=1e9+7,Mod=mod-1,INF=2e9+7;const db eps=1e-5;
int b,p,m,n,H,B[40],x,Ct,op[40];ll Ans,Ps=1;vector<ll> S[40],G[40],Q[40];char c;map<int,int> f;
void calc(int w){
	int P=(b-w*m)/p,i,j;ll l=0,r=2e18,mid;while(l+1<r) {
		mid=l+r>>1;int Ts=0;ll As=1;for(j=H;~j;j--) op[j]&&(As*=B[j]);for(j=H;j;j--){
			!op[j]&&(As*=B[j]);As^Ps&&(Ts+=S[j].end()-LB(S[j].begin(),S[j].end(),(mid+Ps-As-1)/(Ps-As)),0);
		}(Ts>=P?l:r)=mid;
	}ll ToT=0,As=1;int Ts=0;for(i=0;i<=H;i++) ToT+=(Q[i].size()?Q[i][0]:0),!op[i]&&(ToT*=B[i]);for(i=0;i<=H;i++) op[i]&&(ToT*=B[i]);
	for(j=H;~j;j--) op[j]&&(As*=B[j]);for(j=H;j;j--) {!op[j]&&(As*=B[j]);if(As==Ps) continue;int p=LB(S[j].begin(),S[j].end(),(r+Ps-As-1)/(Ps-As))-S[j].begin();Ts+=S[j].size()-p;ToT+=(p<S[j].size()?Q[j][p]:0)*(Ps-As);}
	ToT+=(P-Ts)*l;Ans=max(Ans,ToT);//cerr<<Ans<<'\n';
}
void dfs(int x,int w){if(w*m>b) return;if(x==Ct+1) return calc(w);dfs(x+1,w);for(int i=0;i<G[x].size();i++) op[G[x][i]]=1,dfs(x+1,w+i+1);for(int i=0;i<G[x].size();i++) op[G[x][i]]=0;}
int main(){
	freopen("1.in","r",stdin);
	int i,j;scanf("%d%d%d%d",&n,&b,&p,&m);B[0]=1;S[0].PB(1);for(i=1;i<=n;i++) {cin>>c;scanf("%d",&x);if(c=='*'&&x==1) continue;if(c=='*') Ps*=x,B[H]=x,!f.count(x)&&(f[x]=++Ct),G[f[x]].PB(H),B[++H]=1;else S[H].PB(x);}
	for(i=0;i<=H;i++){sort(S[i].begin(),S[i].end());Q[i]=S[i];for(j=S[i].size()-2;j>=0;j--) Q[i][j]+=Q[i][j+1];}dfs(1,0);printf("%lld\n",Ans);
}
posted @ 2022-10-26 13:01  275307894a  阅读(31)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end