首页 > 其他分享 >C. 在表格里造序列

C. 在表格里造序列

时间:2024-08-19 15:04:23浏览次数:11  
标签:lfloor right 里造 表格 int sum rfloor 序列 left

题意

对于每一对满足 \(1\le i,j\le n\) 的 \((i,j)\),计算有多少个长度为 \(m\) 的序列,权值在 \([1,n]\) 之间且 \(\gcd(a_1,a_2,...,a_m)=\gcd(i,j)\)。答案对 \(998244353\) 取模。


思路

方法:莫比乌斯反演+杜教筛

不会莫比乌斯反演? 出门右转:OI-wiki
不会杜教筛? 出门右转:OI-wiki

现在进入正文部分。

首先,我们考虑他的子问题:计算有多少个长度为 \(m\) 的序列,权值在 \([1,n]\) 之间且 \(\gcd(a_1,a_2,...,a_m)=k\)。

显然的,\(a_i\) 一定是 \(k\) 的倍数。则我们给所有数同时除 \(k\),现在就权值就变成了 \(\left[1,\left\lfloor\frac nk\right\rfloor\right]\),限制也变成了 \(\gcd(a_1,a_2,...,a_m)=1\)。

我们设 \(f_i\) 表示 \(\gcd(a_1,a_2,...,a_m)=i\) 的方案数,\(g_i\) 表示仅仅满足 \(i|a_j\) 的方案数。这也意味着 \(g_i\) 计算的是 \(i|\gcd(a_1,a_2,...,a_m)\) 的方案数。

那么显然的,\(g_k=\left\lfloor\frac nk\right\rfloor^m\)。而且,\(f\) 和 \(g\) 还满足以下关系式:

\[g_k=\sum_{k|d}f_d \]

那么根据莫比乌斯反演的式子,则有:

\[f_k=\sum_{k|d}\mu\left(\frac dk\right)g(d) \]

我们令 \(d=ik\),则:

\[f_k=\sum_{i=1}^{\left\lfloor n/k\right\rfloor}\mu(i)g(ik)=\sum_{i=1}^{\left\lfloor n/k\right\rfloor}\mu(i)\left\lfloor\frac n{ik}\right\rfloor^m \]

现在我们知道了子问题的答案,那么总问题的呢?

答案就很显然了!就是这个式子:

\[\sum_{i=1}^n\sum_{j=1}^nf_{\gcd(i,j)} \]

当然,这个式子肯定是过不了的。于是我们考虑推式子。

\[\begin{align*} &\sum_{i=1}^n\sum_{j=1}^nf_{\gcd(i,j)}\\ =&\sum_{k=1}^n\sum_{i=1}^n\sum_{j=1}^n[\gcd(i,j)=k]f_k\\ =&\sum_{k=1}^nf_k\sum_{i=1}^{\left\lfloor n/k\right\rfloor}\sum_{j=1}^{\left\lfloor n/k\right\rfloor}[\gcd(i,j)=1]\\ \end{align*} \]

现在又要用到狄利克雷卷积的基本式:\(\epsilon=\mu*1\)。也就是说:

\[\sum_{d|n}\mu(d)=[n=1] \]

所以我们的式子又变成了这个样子:

\[\begin{align*} &\sum_{k=1}^nf_k\sum_{i=1}^{\left\lfloor n/k\right\rfloor}\sum_{j=1}^{\left\lfloor n/k\right\rfloor}[\gcd(i,j)=1]\\ =&\sum_{k=1}^nf_k\sum_{i=1}^{\left\lfloor n/k\right\rfloor}\sum_{j=1}^{\left\lfloor n/k\right\rfloor}\sum_{d|\gcd(i,j)}\mu(d)\\ =&\sum_{k=1}^nf_k\sum_{i=1}^{\left\lfloor n/k\right\rfloor}\sum_{j=1}^{\left\lfloor n/k\right\rfloor}\sum_{d|i,d|j}\mu(d)\\ =&\sum_{k=1}^nf_k\sum_{d=1}^{\left\lfloor n/k\right\rfloor}\sum_{i=1}^{\left\lfloor n/kd\right\rfloor}\sum_{j=1}^{\left\lfloor n/kd\right\rfloor}\mu(d)\\ =&\sum_{k=1}^nf_k\sum_{d=1}^{\left\lfloor n/k\right\rfloor}\mu(d)\left\lfloor\frac{n}{kd}\right\rfloor^2\\ =&\sum_{k=1}^n\left(\sum_{i=1}^{\left\lfloor n/k\right\rfloor}\mu(i)\left\lfloor\frac n{ik}\right\rfloor^m\right)\left(\sum_{d=1}^{\left\lfloor n/k\right\rfloor}\mu(d)\left\lfloor\frac{n}{kd}\right\rfloor^2\right)\\ \end{align*} \]

发现了吗? 两个式子竟长的如此相似!

于是我们考虑里面的式子可以用整除分块做。而观察到每一个除法都带有 \(\left\lfloor\frac nk\right\rfloor\) 的因式,于是也可以对 \(k\) 做整除分块。

因为 \(n\) 有 \(10^9\),于是要用杜教筛算 \(\mu\) 函数。


代码

#include <bits/stdc++.h>
#pragma GCC optimize(2)

using namespace std;

#define map unordered_map
#define int long long

#define fileio(x,y) freopen(x,"r",stdin),freopen(y,"w",stdout)
#define tup tuple<int,int,int>
#define pii pair<int,int>
#define bit(x) bitset<x>
#define pb emplace_back
#define mt make_tuple 
#define mp make_pair

const int   mod=998244353;
const int   maxn=2e6+10;

map<int,int>    mu,pp;
bit(maxn)       vis;
int             summu[maxn];
int             pri[maxn];
int             n,m,cnt;

int power(int a,int b,int p) { int tar=1; for(; b; b>>=1,a=1ll*a*a%p) if(b&1) tar=1ll*tar*a%p; return tar; }

int calcMu(int x)
{
    if(x<maxn) return summu[x];
    if(mu[x]) return mu[x];
    int val=1;
    for(int l=2,r; l<=x; l=r+1)
    {
        r=(x/(x/l));
        (val-=calcMu(x/l)*(r-l+1)%mod)%=mod;
    }
    return (mu[x]=val);
}

void init()
{
    summu[1]=1;
    for(int i=2; i<maxn; i++)
    {
        if(!vis[i]) { pri[++cnt]=i; summu[i]=-1; }
        for(int j=1; j<=cnt&&i*pri[j]<maxn; j++)
        {
            vis[i*pri[j]]=true;
            if(i%pri[j]==0) { summu[i*pri[j]]=0; break; }
            summu[i*pri[j]]=-summu[i];
        }
    }
    for(int i=1; i<maxn; i++) (summu[i]+=summu[i-1])%=mod;
    return;
}

void work()
{
    /* Code */
    cin>>n>>m;
    // n=1e9,m=1e18;
    int tar=0; m%=(mod-1);
    for(int l=1,r; l<=n; l=r+1) { r=(n/(n/l)); pp[n/l]=power(n/l,m,mod); }
    for(int l=1,r; l<=n; l=r+1)
    {
        r=(n/(n/l));
        // initialization
        int temp=n/l,tar1=0,tar2=0;
        for(int p=1,q; p<=temp; p=q+1)
        {
            q=(temp/(temp/p));
            int qmu=calcMu(q)-calcMu(p-1);
            (tar1+=pp[temp/p]*qmu%mod)%=mod;
            (tar2+=qmu*(temp/p)%mod*(temp/p)%mod)%=mod;
        }
        tar+=(r-l+1)*tar1%mod*tar2%mod;
    }
    cout<<(tar%mod+mod)%mod<<'\n';
    return;
}

signed main()
{
    // fileio(".in",".out");
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t,stTime=clock();
    init();
    t=1;
    while(t--) work();
    // cerr<<"Time : "<<(double)(clock()-stTime)/CLOCKS_PER_SEC<<'\n';
    return 0;
} // Texas yyds !!!

标签:lfloor,right,里造,表格,int,sum,rfloor,序列,left
From: https://www.cnblogs.com/ninler/p/18367084

相关文章

  • 【Python-办公自动化】1秒提取多个word表格汇总至1个excel内
    欢迎来到"花花ShowPython",一名热爱编程和分享知识的技术博主。在这里,我将与您一同探索Python的奥秘,分享编程技巧、项目实践和学习心得。无论您是编程新手还是资深开发者,都能在这里找到有价值的信息和灵感。自我介绍:我热衷于将复杂的技术概念以简单易懂的方式呈现给大家,......
  • 2024年新SCI顶刊算法蛇鹭优化算法SBOA优化Transformer-LSTM模型的多变量时间序列预测
    matlabR2024a以上一、数据集二、2024年新SCI顶刊算法蛇鹭优化算法SBOA2024年,YFu受到自然界中鹭鹰生存行为启发,提出了鹭鹰优化算法(SecretaryBirdOptimizationAlgorithm,SBOA)。2.1算法思想SBOA生存需要不断地寻找猎物和躲避捕食者的追捕,探索阶段模拟鹭鹰捕食蛇,而......
  • Winform(Devexpress)中实现GridView(GridControl)没有数据时,表格显示图片
    1.问题描述:在GridView中当数据源为空或者没有数据时,Grid表格下的画布显示图片;当然要使用到GridView事件:事件是:CustomDrawEmptyForeground代码如下:privatevoid_GridView_CustomDrawEmptyForeground(objectsender,CustomDrawEventArgse){if(_......
  • 如何批量开展单因素COX回归分析形成表格?
    在统计分析过程中,如果有生存时间数据,那么就需要用到生存分析,COX回归了!SPSS进行COX回归的操作简单,输出也快速,但只能逐个选入变量进行单因素回归,我们在实际分析中遇到的往往是多个变量进行Cox分析,变量多了,SPSS的单因素分析过程与结果整理就显得十分繁琐!而R语言可以批量进行C......
  • R语言的logistic回归分析结果如何快速整合到表格中?
    在使用R语言进行logistic回归时,总是不能一步到位完成结果的整理,目前常见的glm函数需要在一堆结果中逐行比照,如果有更多的变量,结果整理难度也会大大增加!autoreg函数虽然结果展示相对简洁,但仍需要手动处理,比如将OR值和P值拆分到2个表格中,同样也是变量越多,结果整理越困难!......
  • 利用生成模型进行时间序列数据的无监督对齐「Alignment」
    作者单位:ChampalimaudCentrefortheUnknown「葡萄牙一个生物研究所」一、主线任务1、研究背景大型推理模型在神经科学中被广泛用于从高维神经记录中提取潜在表示。由于不同实验和动物之间的统计异质性,通常需要针对每个新数据集从头开始训练模型,这既耗费计算资源,也没有......
  • 序列(dp+矩阵加速)
    第2题   序列 查看测评数据信息给定一个数集A,现在你需要构造一个长度为k的序列B,序列B的元素从数集A中任意挑选,要求B中任意相邻的两个数字的异或值二进制表示中1的个数是3的倍数,请问B的有多少种合法的构造方案?两种方案不同当且仅当存在B[i]在A中的位置不同。输入格式......
  • 对象流,序列化和反序列化 day18
    packagecom.shujia.day18.ketang;importjava.io.*;/*序列化流:序列化:将一个对象转换成网络中传输的流对象输出流:ObjectOutputStream将一个类的对象写进文本中反序列化:将网络中传输的流还原成一个对象对象输入流:Object......
  • JAVA中的序列化
    Java序列化是一种机制,它可以将对象状态转换为可存储或可传输的形式。序列化后的对象可以在网络上传输,或者保存到文件、数据库等存储介质中。在Java中,序列化通过实现 java.io.Serializable接口来实现。本文将详细介绍Java序列化的概念、实现方式、优缺点以及代码示例。一、序......
  • JAVA中的反序列化
    Java反序列化是将之前序列化存储的对象状态信息重新恢复为Java对象的过程。这个过程与序列化是相反的,它允许程序从字节流中重建对象,这对于网络传输、对象持久化以及分布式系统中的对象传递至关重要。下面将详细介绍Java反序列化的概念、实现方式、安全注意事项,并通过一个......