AtCoder Beginner Contest 220

A - Find Multiple

签到水题 找好边界关系就好

代码

#include <iostream>
 
using namespace std;
 
int a, b, c; 
 
void solve()
{
	scanf("%d%d%d", &a, &b, &c);
	int x1 = a / c, x2 = b / c;
	int y1 = a % c, y2 = b % c;
	
	if (x2 - x1 >= 1) printf("%d\n", (x1 + 1) * c);
	else if (x1 == x2 && !y1) printf("%d\n", a);
	else puts("-1");
}
 
int main()
{
	solve();
	return 0;
}

B - Base K

进制转换 水题

代码

#include <iostream>
#include <cstring>
 
using namespace std;
 
typedef long long ll;
 
ll ax, bx, k; 
string a, b;
 
void solve()
{
	scanf("%lld", &k);
	cin >> a >> b;
	ax = 0, bx = 0;
	
	int t = 1;
	for (int i = a.size() - 1; i >= 0; i -- )
	{
		if (a[i] >= '0') ax += t * (a[i] - '0');
		t *= k;
	}
	t = 1;
	for (int i = b.size() - 1; i >= 0; i -- )
	{
		if (b[i] >= '0') bx += t * (b[i] - '0');
		t *= k;
	}
	printf("%lld\n", ax * bx);
}
 
int main()
{
	solve();
	return 0;
}

C - Long Sequence

水题 维护一下整个数组的sum 然后求最后一组要多出来几个才能大于x 相加就能得答案

代码

#include <iostream>
#include <cstring>
 
using namespace std;
 
typedef long long ll;
 
const int N = 1e5 + 10;
 
ll ans;
ll a[N], x, n;
ll sum;
 
void solve()
{
	
}
 
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i ++ ) cin >> a[i], sum += a[i];
	cin >> x;
	x ++ ;
	ans = x / sum * n;
	x = x % sum;
 
	for (int i = 1; i <= n; i ++ )
	{
		if (x > 0) 
		{
			ans ++ ;
			x -= a[i];
		}
		else
		{
			cout << ans << endl;
			return 0;
		}
	}
	cout << ans;
	return 0;
}

D - FG operation

dp题 题意为给定一个数组通过一直进行两种操作之一 从而使得最终数组长度为1 问最终数组剩余数字为 0~9 的种类数量
我们可以进行这样一个思考 :每次进行操作之后 我们可以得到的最左边数字是由操作前最左边数字与相邻数字相加或相乘得到的 则我们可以得到这样一个状态方程 用 f [ i ] [ j ] 来表示第 i 次操作 以 j 结尾的方案个数 可以得到这样的状态转移方程 :

// 记得还要把jmod10一下
f[i][j * a[i]] += f[i - 1][j];
f[i][j + a[i]] += f[i - 1][j];

所以直接写出代码就好了

代码

#include <iostream>
 
using namespace std;
 
const int N = 1e5 + 10, P = 998244353;
 
int n;
int a[N], f[N][11];
 
int main()
{
	scanf("%d", &n);
	
	for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
	
	f[1][a[1]] = 1;
	for (int i = 2; i <= n; i ++ )
	{
		for (int j = 0; j <= 9; j ++ )
		{
			f[i][(j + a[i]) % 10] += f[i - 1][j];
			f[i][(j + a[i]) % 10] %= P;
			f[i][(j * a[i]) % 10] += f[i - 1][j];
			f[i][(j * a[i]) % 10] %= P;
		}
	}
	
	for (int i = 0; i <= 9; i ++ )
		printf("%d\n", f[n][i]);
	
	return 0;
}

F - Distance Sums 2

给定一棵树 问每个点到其他所有点的距离总和为多少 可以看作是树形dp
对于一个结点 他的答案可以看作从下往上到所有点的距离 加上 从上往下所有点的距离 即
在这里插入图片描述

对于蓝色点的答案 我们可以通过所有红色点答案 加上 蓝色点所有子结点个数乘以1(从所有红色结点到蓝色结点要加一条边) 则可以得到蓝色点由上往下的答案 再去求由下往上答案 即绿色结点减去整个左边结点的答案 相加即为最终答案

代码

#include <iostream>
#include <cstring>
 
using namespace std;
 
typedef long long ll;
 
const int N = 2e5 + 100, M = N * 2;
 
int n;
ll sz[N], ans[N], sub[N];
int h[N], e[M], ne[M], idx;
 
void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
 
void dfs(int u, int fa)
{
	for (int i = h[u]; ~i; i = ne[i])
	{
		int j = e[i];
		if (j == fa) continue;
		dfs(j, u);
		sz[u] += sz[j];
		sub[u] += sub[j];
	}
	sub[u] += sz[u];
	sz[u] ++ ;
}
 
void dfs(int u, int fa, ll fromup)
{
	ans[u] = fromup + sub[u];
	for (int i = h[u]; ~i; i = ne[i])
	{
		int j = e[i];
		if (j == fa) continue;
		ll f = n - sz[j] + fromup + sub[u] - sz[j] - sub[j];
		dfs(j, u, f);
 	}
}
 
signed main()
{
	scanf("%d", &n);
	
	memset(h, -1, sizeof h);
	for (int i = 1; i < n; i ++ )
	{
		int a, b;
		scanf("%d%d", &a, &b);
		add(a, b), add(b, a);
	}
	
	dfs(1, 0);
	dfs(1, 0, 0);
	
	for (int i = 1; i <= n; i ++ ) printf("%lld\n", ans[i]);
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值