AtCoder Beginner Contest 192

AtCoder Beginner Contest 192

D

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

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

对于当前进制 b,从低位开始计算当前的值,如果发现比限制大了就返回 false,注意到二分的 mid 上限是 1018,也就是计算当前的值过程中可能会爆 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 当然需要满足:tX(modk)

记每个物品重 wi,并令 ci=wi%kr=X%k

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

那么使用 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 @   HinanawiTenshi  阅读(53)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2021-07-06 【BCC】冗余路径(做法 + 证明)
点击右上角即可分享
微信分享提示