koishi的数学题
题目链接:koishi的数学题
题目大意
给你一个公式,让你求结果(详细看题目链接里面)
题目题解
如果出这种题,我就死定了(真的
看了一下,不会 那就打表。打了半天表没发现什么,因为(n)也在变,每次答案都不一样,然后我换了个思路,对于每一位上的数针对(n)不同又是怎么变得呢?
于是我对于每一位又打了个表 (x代表没有数
1 -> 0 1 2 3 4 5 6 7 8 9
2 -> x 2 4 6 8 10 12 14 16
3 -> x x 1 4 7 10 13 16 19 22
4 -> x x x 1 5 9 13 17 21 25
5 -> x x x x 4 9 14 19 24 29
6 -> x x x x x 3 9 15 21 27
7 -> x x x x x x 8 15 22 29
8 -> x x x x x x x 8 16 24
9 -> x x x x x x x x 12 21
10 -> x x x x x x x x x 13
然后发现对于每一位而言,第一位不知道怎么算出来的,然后接下来每一位都是由前一位加(i)得到的
那么很明显了,我们只要得到第一位就能通过O(1)的式子转化到最终答案,但显然 这个第一位不是那么好求,本来想打表的,但是跑了很长时间都没有跑出来,然后就想了其他的办法(看题解)
最终发现第一个题解的办法有点像这个,看了一下 哦!原来可以这样
对于每一个固定的(i),(x)递增时的(x - (xMODi)) ,这就是每(i)项增加(i)的一个数列,因为由上面我们打表可得,每一项都是由前一项得到,我们理所应当的就能想到递推式
代码如下 (这种题 quq我还是少写吧)
//#define fre yes
#include <cstdio>
const int N = 1000005;
long long n, ans, tag[N];
int main() {
static int n;
scanf("%lld", &n);
for (int i = 2; i <= n; i++) {
for (int j = i; j <= n; j += i) {
tag[j] += i;
}
}
for (int i = 1; i <= n; i++) {
ans += n - tag[i] - 1;
printf("%lld ", ans);
} return 0;
}