Cf Round 928 (Div.4)-C. Vlad and a Sum of Sum of Digits
Please note that the time limit for this problem is only 0.5 seconds per test.
Vladislav wrote the integers from 1 to n, inclusive, on the board. Then he replaced each integer with the sum of its digits.
What is the sum of the numbers on the board now?
For example, if n=12=12 then initially the numbers on the board are:
1,2,3,4,5,6,7,8,9,10,11,12.1,2,3,4,5,6,7,8,9,10,11,12.
Then after the replacement, the numbers become:1,2,3,4,5,6,7,8,9,1,2,3.1,2,3,4,5,6,7,8,9,1,2,3.
The sum of these numbers is 1+2+3+4+5+6+7+8+9+1+2+3=511+2+3+4+5+6+7+8+9+1+2+3=51. Thus, for n=12 the answer is 5151.
**请注意,本问题每次测试的时间限制仅为 0.5 秒。
弗拉迪斯拉夫在黑板上写下了从 1 到 n 的整数。弗拉迪斯拉夫在黑板上写下了从 1 到 n 的整数,然后将每个整数替换为其数位之和。
现在黑板上的数字之和是多少?
例如,如果是 n=12 ,那么最初黑板上的数字是
1,2,3,4,5,6,7,8,9,10,11,12.1,2,3,4,5,6,7,8,9,10,11,12.
那么在替换之后,数字变成了1,2,3,4,5,6,7,8,9,1,2,3.1,2,3,4,5,6,7,8,9,1,2,3.
这些数字之和为 1+2+3+4+5+6+7+8+9+1+2+3=511+2+3+4+5+6+7+8+9+1+2+3=51 。因此,对于 n=12 ,答案是 5151 。
最大的问题是时间限制只有0.5秒。。
比赛的时候用的前缀和,但是数据量的问题,加上计算数位和需要一个while语句,所以当时也是不出意料的TLE了(菜,就多练)
题目的答案其实是固定的。n = 7的时候答案就是51,n = 12的时候答案就是5151。所以可以在一开始对答案进行预处理,将我们会用到的答案全部存入ans数组,最后输出对应的元素即可。
尽量压缩时间,函数写计算数位和。
AC代码:
#include<iostream>
#include<algorithm>
#include<cmath>
typedef long long ll;
const int M = 200005;
using namespace std;
int ans[M];
int plx(int x)
{
int ans = 0;
while (x)
{
ans += (x % 10);
x /= 10;
}
return ans;
}
void solve()
{
int n;
cin >> n;
cout << ans[n] << '\n';
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
for (int i = 1; i < M; i++)
ans[i] = plx(i) + ans[i - 1];
int t;
cin >> t;
while (t--)
solve();
return 0;
}
洛谷P1605-迷宫
题目描述
给定一个 N×M 方格的迷宫,迷宫里有 T 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 N,M,T,分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 SX,SY,FX,FY,SX,SY 代表起点坐标,FX,FY 代表终点坐标。
接下来 T 行,每行两个正整数,表示障碍点的坐标。
DFS板子题,今天重新写了一下。
二维数组DFS用到表示方向的d数组。
d[5] = {-1,0,1,0,-1}
此时定义x和y方向的新变量,通过两个变量模拟四个方向的移动
对于判断是否接下来的一格,用f的值决定。注意的是,每次DPS之后要回溯到初始状态。
AC代码:
#include<iostream>
#include<algorithm>
#include<cmath>
typedef long long ll;
const int M = 200005;
using namespace std;
int n, m, t,cnt;
int sx, sy, fx, fy;
int a[15][15],f[15][15];
int d[5] = { -1,0,1,0,-1 };
void dfs(int x,int y)
{
if (x == fx && y == fy)
{
cnt++;
return;
}
for (int i = 0; i < 4; i++)
{
int l = x + d[i];
int r = y + d[i+1];
if (l >= 1 && r >= 1 && l <= n && r <= m && a[l][r] == 0 && f[l][r] == 0)
{
f[l][r] = 1;
dfs(l, r);
f[l][r] = 0;
}
}
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m >> t>> sx >> sy >> fx >> fy;
a[sx][sy] = 1;
int p, q;
for (int i = 1; i <= t; i++)
{
cin >> p >> q;
a[p][q] = 1;
}
dfs(sx, sy);
cout << cnt << '\n';
return 0;
}
Acwing-每日一题:改变数组元素
解法一:
思路:数字越大,改变的数字就越多。最终的数组构成,位于后面的数字可以覆盖前面的数字。可以从后往前遍历数组a,找到左边界,并将从左边界到当前位的元素都变为“1”。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
typedef long long ll;
const int M = 2000010;
const int INF = 0x3f3f3f3f;
using namespace std;
int a[M];
void solve()
{
int n;
cin >> n;
memset(a,0,sizeof(a))
for (int i = 1; i <= n; i++)
cin >> a[i];
int l = INF;
for (int i = n; i >= 1; i--)
{
l = min(l, i - a[i] + 1);
if (l <= i)
a[i] = 1;
}
for (int i = 1; i <= n; i++)
cout << a[i] << ' ';
cout << '\n';
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
解法二:差分
可以当差分板子的一道题(本来在Acwing就是板子题。。)
核心代码是作为模板的cf函数和前缀和操作。因为差分可以看作前缀和的逆运算。(差分数组进行前缀和 == 原数组)
AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
typedef long long ll;
const int M = 200005;
using namespace std;
int a[M];
void cf(int x, int y)
{
a[x]++;
a[y + 1]--;
}
void solve()
{
int n, k;
cin >> n;
memset(a, 0, size(a));
for (int i = 1; i <= n; i++)
{
cin >> k;
if (k == 0)
continue;
else if (k >= i)
cf(1, i);
else
cf(i - k + 1, i);
}
for (int i = 1; i <= n; i++)
a[i] += a[i - 1];
for (int i = 1; i <= n; i++)
{
if (a[i] == 0)
cout << 0 << ' ';
else
cout << 1 << ' ';
}
cout << '\n';
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
return 0;
}