• LOJ#6714. Stupid Product


    题面

    题解

    考虑枚举序列最后一个位置的数字,得到 (f(x)) 的转移方程:

    [f(x) = egin{cases} 1 & x = 1 \ sum_{d|x, d eq x} f(d) & x > 1 end{cases} ]

    (S(n) = sum_{i=1}^n f(i)),则

    [S(n) = 1 + sum_{i=2}^n sum_{d|i,d eq i} f(d) ]

    两边同时加上 (S(n)) 得:

    [egin{aligned}2 S(n) &= 1 + sum_{i=1}^n sum_{d|i} f(d) \&= 1 + sum_{d=1}^n sum_{i=1}^{leftlfloor frac {n}{d} ight floor} f(i) \&= 1 + sum_{d=1}^n Sleft(leftlfloor frac {n}{d} ight floor ight)end{aligned} ]

    于是有:

    [S(n) = 1 + sum_{d=2}^n Sleft(leftlfloor frac {n}{d} ight floor ight) ]

    杜教筛即可。

    代码

    #include <cstdio>
    
    const int M(5e6), N(M + 10), Mod(998244353);
    int tot = 1, f[N], s[2500]; long long n;
    inline int F(long long x) { return x <= M ? f[x] : s[n / x]; }
    void Init()
    {
    	int m = n < M ? n : M;
    	for (int i = f[1] = 1; i <= m; i++)
    		for (int j = i << 1; j <= m; j += i) f[j] = (f[j] + f[i]) % Mod;
    	for (int i = 1; i <= m; i++) f[i] = (f[i] + f[i - 1]) % Mod;
    }
    
    int main()
    {
    	scanf("%lld", &n), Init(); while (n / tot > M) ++tot;
    	for (int t = tot; t; s[t] = (s[t] + 1) % Mod, t--)
    		for (long long i = 2, j, x = n / t; i <= x; i = j + 1)
    			j = x / (x / i), s[t] = (s[t] + (j - i + 1) * F(x / i)) % Mod;
    	printf("%d
    ", F(n));
    	return 0;
    }
    
  • 相关阅读:
    Shell编程笔记
    Git学习笔记
    JavaScript+jQuery实现简单的动态菜单
    JSON表单提交(ajax异步刷新)
    Json简单实例
    jsp分页
    浅谈this关键字
    Servlet+Javabean+Html实现简单的查询.删除.修改.添加四个功能
    Tomcat的安装与在myeclips中的配置
    jsp页面实现增删修改和查询
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/12207437.html
Copyright © 2020-2023  润新知