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;
}