AtCoder Beginner Contest 192 略解

本场链接:AtCoder Beginner Contest 192

A - Star

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)	


int main() 
{
	int x;cin >> x;
	int res = 0;
	while(x % 100)	++res,++x;
	cout << (res == 0 ? 100 : res) << endl;
	return 0;
} 

B - uNrEaDaBlE sTrInG

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)	

const int N = 1005;
char s[N];

int main() 
{
	scanf("%s",s + 1);int n = strlen(s + 1);
	bool ok = 1;
	for(int i = 1;i <= n;i += 2)	if(s[i] >= 'A' && s[i] <= 'Z')	ok = 0;
	for(int i = 2;i <= n;i += 2)	if(s[i] >= 'a' && s[i] <= 'z')	ok = 0;
	if(!ok)	puts("No");
	else puts("Yes");
	return 0;
}

C - Kaprekar Number

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)	

void divide(vector<int>& res,int n)
{
	res.clear();
	while(n)
	{
		res.push_back(n % 10);
		n /= 10;
	}
	reverse(res.begin(),res.end());
}

int gback(vector<int>& o)
{
	int res = 0;
	for(int i = 0;i < o.size();++i)
		res = 10 * res + o[i];
	return res;
}

int main() 
{
	int n,k;scanf("%d%d",&n,&k);
	vector<int> dup,ddw;
	forn(i,1,k)
	{
		divide(dup,n);
		sort(dup.begin(),dup.end());
		ddw = dup;
		reverse(ddw.begin(),ddw.end());
		n = gback(ddw) - gback(dup); 
	}
	printf("%d",n);
	return 0;
}

D - Base n

以进制\(p\)表示的数,是随着\(p\)的增大而增大的,具有单调性.可以对最大的\(p\)二分.特判:没有任何一种情况符合时需要让求出的左边界往左挪一位.对于一个数的等价于十进制下判断.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)	

ll M;

bool check(string& s,ll p)
{
	ll res = 0;
	for(auto& v : s)
	{
		if(res > M / p)	return 0;
		res *= p;
		res += v - '0';
	}
	return res <= M;
}

int main() 
{
	string x;cin >> x;
	cin >> M;

	if(x.size() == 1)
	{
		cout << check(x,10);
		return 0;
	}
	int d = 0;
	for(auto& v : x)	d = max(d,v - '0');
	++d;
	ll l = d,r = 2e18;
	while(l < r)
	{
		ll mid = l + r + 1 >> 1;
		if(check(x,mid))	l = mid;
		else r = mid - 1;
	}
	if(!check(x,l))	--l;
	printf("%lld",l - d + 1);
	return 0;
}

E - Train

模型就是一个最短路,考虑怎么解决本题:事实上就是把拓展距离的大小换了一下求的办法,不影响dijkstra正确性.

注意特判一些情况.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)	
typedef pair<ll,int> pli;
#define x first
#define y second

const int N = 1e5+7,M = 2 * N;
const ll INF = 1e18;

int edge[M],succ[M],stt[M],ett[M],ver[N],idx;
ll dist[N];
bool st[N];
int n,m,STT,EDD;

void add(int u,int v,int w1,int w2)
{
	edge[idx] = v;
	ett[idx] = w1;
	stt[idx] = w2;
	succ[idx] = ver[u];
	ver[u] = idx++;
}

ll dijkstra(int STT,int EDD)
{
	priority_queue<pli,vector<pli>,greater<pli>> pq;
	forn(i,1,n)	dist[i] = INF;
	pq.push({0,STT});dist[STT] = 0;
	while(!pq.empty())
	{
		auto _ = pq.top();pq.pop();
		ll d = _.x;int u = _.y;
		if(st[u])	continue;
		st[u] = 1;
		for(int i = ver[u];~i;i = succ[i])
		{
			int v = edge[i];
			ll cost = ett[i] + (d == 0 ? 0 : stt[i] - (d % stt[i] == 0 ? stt[i] : d % stt[i]));
			if(dist[v] > d + cost)
			{
				dist[v] = d + cost;
				pq.push({dist[v],v});
			}
		}
	}
	return dist[EDD] == INF ? -1 : dist[EDD];
}


int main() 
{
	memset(ver,-1,sizeof ver);
	scanf("%d%d%d%d",&n,&m,&STT,&EDD);
	forn(i,1,m)
	{
		int u,v,w1,w2;scanf("%d%d%d%d",&u,&v,&w1,&w2);
		add(u,v,w1,w2);add(v,u,w1,w2);
	}
	
	printf("%lld",dijkstra(STT,EDD));
	
	return 0;
}

F - Potion

考虑dp.

状态:\(f[i][j][k]\)表示在前\(i\)个数中选出\(j\)个数时,和模\(j\)的结果是\(k\)的最大和是多少.

接下来考虑如何转移:可以发现如果直接简单的枚举,那么和取模的结果比较难算.更好的处理办法是直接做多次dp,每次强制限制选出的个数是\(C\).最后统计答案.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)	

const int N = 105;
ll f[N][N][N],a[N];

inline void chmax(ll& res,ll tar)
{
	res = max(res,tar);
}

int main() 
{
	ios::sync_with_stdio(0);cin.tie(0);
	ll n,target;cin >> n >> target;
	forn(i,0,n - 1)	cin >> a[i];
	
	ll res = 2e18;
	forn(C,1,n)
	{
		forn(i,0,n)	forn(j,0,C)	forn(k,0,C)	f[i][j][k] = -1e18;
		f[0][0][0] = 0;
		forn(i,0,n - 1)	forn(j,0,C)	forn(k,0,C - 1)
		{
			chmax(f[i + 1][j][k],f[i][j][k]);
			if(j < C)	chmax(f[i + 1][j + 1][(k + a[i]) % C],f[i][j][k] + a[i]);
		}
		if(f[n][C][target % C] < 0)	continue;
		res = min(res,(target - f[n][C][target % C]) / C);
	}

	cout << res;
	return 0;
}
上一篇:手把手教你——linux磁盘分区


下一篇:centos7防火墙放开某一端口