[Luogu P3708] koishi的数学题

洛谷传送门

题目描述

Koishi在Flandre的指导下成为了一名数学大师,她想了一道简单的数学题。

输入一个整数n,设 f(x)=ni=1x mod i f ( x ) = ∑ i = 1 n x   m o d   i ,你需要输出 f(1),f(2)...f(n) f ( 1 ) , f ( 2 ) . . . f ( n )

按照套路,Koishi假装自己并不会做这道题,就来求你帮忙辣。

输入输出格式

输入格式:

一个正整数 n n

输出格式:

一行用空格分隔的 n个整数 f(1),f(2)...f(n) f ( 1 ) , f ( 2 ) . . . f ( n )

输入输出样例

输入样例#1:
10
输出样例#1:
9 16 22 25 29 27 29 24 21 13

说明

对于20%的数据, n1000 n ≤ 1000

对于60%的数据, n105 n ≤ 10 5

对于100%的数据, 1n106 1 ≤ n ≤ 10 6

解题分析

首先, 我们构造一组样例观察一下: 设 n=10 n = 10

f(8)=8%1+8%2+8%3+8%4+8%5+8%6+8%7+8%8+8%9+8%10f(9)=9%1+9%2+9%3+9%4+9%5+9%6+9%7+9%8+9%9+9%10 f ( 8 ) = 8 % 1 + 8 % 2 + 8 % 3 + 8 % 4 + 8 % 5 + 8 % 6 + 8 % 7 + 8 % 8 + 8 % 9 + 8 % 10 f ( 9 ) = 9 % 1 + 9 % 2 + 9 % 3 + 9 % 4 + 9 % 5 + 9 % 6 + 9 % 7 + 9 % 8 + 9 % 9 + 9 % 10

f(9) f ( 9 ) 中绝大多数项都比 f(8) f ( 8 ) 大1, 那么我们就先每项添1

然后我们发现那些不比 f(8) f ( 8 ) 大1的项都为0, 恰好又是 9 9 的因数, 所以可以得到一下递推式:
f(x)=f(x1)+nσ1(x)

所以线筛+递推, 总复杂度 O(n) O ( n )

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstdlib>
#define R register
#define IN inline
#define gc getchar()
#define W while
#define MX 1000500
#define ll long long 
int pri[MX];
ll sum[MX], sgm[MX], ans[MX];
bool npr[MX];
int n, pcnt;
void getsigma0()
{
    R int j, tar;
    sgm[1] = sum[1] = 1;
    for (R int i = 2; i <= n; ++i)
    {
        if(!npr[i]) sum[i] = sgm[i] = i + 1, pri[++pcnt] = i;
        for (j = 1; j <= pcnt; ++j)
        {
            tar = pri[j] * i;
            if(tar > n) break;
            npr[tar] = true;
            if(!(i % pri[j])) {sum[tar] = pri[j] * sum[i] + 1, sgm[tar] = sgm[i] * sum[tar] / sum[i]; break;}
            else sum[tar] = 1 + pri[j], sgm[tar] = sgm[i] * sum[tar];
        }
    }
}
int main(void)
{
    scanf("%d", &n);
    getsigma0();
    ans[1] = n - 1; printf("%lld ", ans[1]);
    for (R int i = 2; i <= n; ++i) ans[i] = ans[i - 1] + n - sgm[i], printf("%lld ", ans[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值