AtCoder Beginner Contest 192

AtCoder Beginner Contest 192

D

注意到只有一位的时候多少进制都一样,方便起见先判掉。

剩下的都是进制越大值越大,考虑二分:

对于当前进制 \(b\),从低位开始计算当前的值,如果发现比限制大了就返回 false,注意到二分的 \(mid\) 上限是 \(10^{18}\),也就是计算当前的值过程中可能会爆 long long,因此可以使用 __int128 来存。

int lim;
vector<int> w;
int n;

bool ok(int b){
	__int128 res=0;
	dwn(i,n-1,0){
		res=res*b+w[i];
		if(res>lim) return false;	
	}
	return true;
} 

signed main(){
	string val;
	cin>>val>>lim;
	if(val.size()==1) return cout<<(stoi(val)<=lim), 0;
	dwn(i,val.size()-1,0) w.pb(val[i]-'0');
	n=w.size();
	
	int mx=*max_element(all(w));
	int l=mx, r=lim+10;
	while(l<r){
		int mid=l+r+1>>1;
		if(ok(mid)) l=mid;
		else r=mid-1;
	}
	cout<<l-mx<<endl;
	
	return 0;
}

E

个人认为比 D 简单。

其实就是最短路的简单变式:

每次贪心地求出到一个点的最短时间,如果要等就让边权相应地加上多等的时间就好了。

const int N=1e5+50, M=2e5+50;

int n, m, S, T;

struct Edge{
	int to, w, k, next;
}e[M];

int h[N], tot;

void add(int u, int v, int w, int k){
	e[tot].to=v, e[tot].w=w, e[tot].k=k, e[tot].next=h[u], h[u]=tot++;
}

int d[N];
bool vis[N];

int dijk(){
	memset(d, 0x3f, sizeof d);
	d[S]=0;
	priority_queue<pii, vector<pii>, greater<pii>> q;
	q.push({0, S});
	
	while(q.size()){
		auto [dist, u]=q.top(); q.pop();
		if(vis[u]) continue;
		vis[u]=true;
		
		for(int i=h[u]; ~i; i=e[i].next){
			int go=e[i].to;
			int k=e[i].k;
			int nwd=d[u]+e[i].w+(d[u]%k? k-d[u]%k: 0);
			if(d[go]>nwd){
				d[go]=nwd;
				q.push({nwd, go});
			}
		}
	}
	
	if(d[T]>1e18) return -1;
	return d[T];
}

signed main(){
	memset(h, -1, sizeof h);
	cin>>n>>m>>S>>T;
	rep(i,1,m){
		int u, v, w, k; read(u), read(v), read(w), read(k);
		add(u, v, w, k), add(v, u, w, k);
	}
	
	cout<<dijk()<<endl;
	
	return 0;
}

F

考虑求出选择 \(k\) 个物品的最大重量 \(t\),其中 \(t\) 当然需要满足:\(t\equiv X\pmod k\)

记每个物品重 \(w_i\),并令 \(c_i = w_i \% k\)\(r=X\% k\)

考虑 DP:\(f(i, s, j)\) 表示前 \(i\) 个物品选择 \(s\) 个使得物品重量 \(\%k\) 的值为 \(j\) 的最大重量。

那么使用 \(\texttt{01}\) 背包进行转移即可。

const int N=110;

int n, m;
int w[N], c[N];

signed main(){
	cin>>n>>m;
	rep(i,1,n) read(w[i]);
	
	int res=2e18;
	rep(k,1,n){
		int r=m%k;
		rep(i,1,n) c[i]=w[i]%k;
		
		int f[n+1][k+1][k];
		memset(f, 0xcf, sizeof f);

		f[0][0][0]=0;
		rep(i,1,n){
			rep(s,1,k){
				dwn(j,k-1,0) f[i][s][j]=max(f[i-1][s][j], f[i-1][s-1][(j-c[i]+k)%k]+w[i]); 
			}
		}

		if(f[n][k][r]>0) res=min(res, (m-f[n][k][r])/k);
	}cout<<res;
	return 0;
}
posted @ 2022-07-06 15:50  HinanawiTenshi  阅读(64)  评论(0)    收藏  举报