koishi的数学题

koishi的数学题

题目描述

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

输入一个整数 n,设 f(x)=i=1nxmodi,你需要输出 f(1),f(2),,f(n)

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

输入格式

一个正整数 n

输出格式

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

样例 #1

样例输入 #1

10

样例输出 #1

9 16 22 25 29 27 29 24 21 13

提示

对于 20% 的数据,n1000。  
对于 60% 的数据,n105。  
对于 100% 的数据,1n106

 

解题思路

  这几天在洛谷跳题,结果很多不会做qwq。

  对于 xmodi,关键是要想到可以转换为 xxii,因此就有

f(x)=i=1nxmodi=i=1nxxii=nxi=1nxii

  接下来可以考虑递推,假设我们已经知道了 f(x)i=1nxii 这部分的结果,考虑能否推出 i=1nx+1ii 的结果。分以下两种情况考虑:

  1. xmodi<i1:那么有 x+1ii=xii
  2. xmodi=i1:那么有 x+1ii=(xi+1)i=xii+i

  即如果 ix+1 的约数,那么 x+1ii 就会比 xii 多出 i,否则相等。因此对于整个 i=1nx+1ii 的结果,就会比 i=1nxii 多出 x+1 的约数和。

  所以对于 x[1,n],我们可以对每个 x 的分解约数求约数和,但这样的时间复杂度为 O(nn)。为此我们可以反过来枚举约数 i[1,n],再枚举所有不超过 ni 的倍数 j,那么这些 j 的都含有约数 i,时间复杂度就是 O(i=1nni)O(nlogn)

  AC 代码如下:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e6 + 10;

LL s[N];

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        for (int j = i; j <= n; j += i) {
            s[j] += i;
        }
    }
    LL last = 0;
    for (int i = 1; i <= n; i++) {
        printf("%lld ", 1ll * i * n + last - s[i]);
        last -= s[i];
    }
    
    return 0;
}

 

参考资料

  题解 P3708 【koishi的数学题】:https://www.luogu.com.cn/blog/asuldb/solution-p3708

posted @   onlyblues  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2022-10-21 C. Save the Magazines
Web Analytics
点击右上角即可分享
微信分享提示