IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 【XSY4350】摆(行列式,数论,杜教筛) -> 正文阅读

[人工智能]【XSY4350】摆(行列式,数论,杜教筛)

题面

题解

首先我们将原矩阵写成 A + B A+B A+B,其中 B B B 全是 C C C,那么 A A A 的第 i i i 行就只有其倍数处有值,且 A i , i = 1 ? C , A i , j ( i ∣ j ∧ i ≠ j ) = ? C A_{i,i}=1-C,A_{i,j(i|j\land i\neq j)}=-C Ai,i?=1?C,Ai,j(iji?=j)?=?C

那么原来的行列式就变成了:
∑ p ( ? 1 ) sgn ? ( p ) ∑ S ? { 1 , ? ? , n } ∏ i ∈ S A i , p i ∏ i ∈? S B i , p i \sum_{p}(-1)^{\operatorname{sgn}(p)}\sum_{S\subseteq \{1,\cdots,n\}}\prod_{i\in S}A_{i,p_i}\prod_{i\not\in S}B_{i,p_i} p?(?1)sgn(p)S?{1,?,n}?iS?Ai,pi??i?S?Bi,pi??
考虑在 A A A 中选的点数( ∣ S ∣ |S| S),发现它不可能小于 n ? 1 n-1 n?1,否则对于 B B B 要求的就是一个大小大于 1 1 1、全是 C C C 的矩阵的行列式,它恒为 0 0 0

那么假设 B B B 中选的那个点( B B B 中没选点的情况很好算,略)为 ( i , p i ) (i,p_i) (i,pi?)。考虑把行列式问题放在图论上(注意到 ( ? 1 ) sgn ? ( p ) (-1)^{\operatorname{sgn}(p)} (?1)sgn(p) ( ? 1 ) n ? 环个数 (-1)^{n-\text{环个数}} (?1)n?环个数,所以系数的问题也是可以处理的),相当于说 B B B 在图上钦定了一条边 i → p i i\to p_i ipi? 必须选,那么在 A A A 中选的就应该是:

  • p i → ? → i p_i\to \cdots\to i pi??i 的一条链,其中每一条边后者是前者的倍数,且边权为 ? C -C ?C
  • 发现剩下的点在 A A A 中都只能选自环(从大往小推每个点即可),边权为 1 ? C 1-C 1?C

假设 f n f_n fn? 表示链尾是 n n n 的所有方案的和,可以得到:
f n = C ( 1 ? C ) n ? 1 + ∑ d ∣ n ∧ d ≠ n C 1 ? C f d f_n=C(1-C)^{n-1}+\sum_{d|n\land d\neq n}\frac{C}{1-C}f_d fn?=C(1?C)n?1+dnd?=n?1?CC?fd?
其中前者是链长为 1 1 1 的方案,后者是链长大于 1 1 1 的方案,枚举链尾的前一个数 d d d,注意环个数的变化所带来的正负号影响。

我们只需要求出 ∑ i = 1 n f n \sum_{i=1}^n f_n i=1n?fn? 即可,发现这也是可以用类似杜教筛的方法来做的:
∑ i = 1 n f i = ∑ i = 1 n ( C ( 1 ? C ) n ? 1 ∑ d ∣ i , d ≠ i C 1 ? C f d ) = n C ( 1 ? C ) n ? 1 + ∑ d = 1 n f d ? C 1 ? C ( ? n d ? ? 1 ) \begin{aligned} \sum_{i=1}^nf_i&=\sum_{i=1}^n\left(C(1-C)^{n-1}\sum_{d|i,d\neq i}\frac{C}{1-C}f_d\right)\\ &=nC(1-C)^{n-1}+\sum_{d=1}^nf_d\cdot\frac{C}{1-C}\left(\left\lfloor\frac{n}{d}\right\rfloor-1\right) \end{aligned} i=1n?fi??=i=1n????C(1?C)n?1di,d?=i?1?CC?fd????=nC(1?C)n?1+d=1n?fd??1?CC?(?dn???1)?
有一个问题是如何线性预处理小范围的 ∑ i = 1 n f i \sum_{i=1}^n f_i i=1n?fi?。发现 f i f_i fi? 只与 i i i 的因子的形态有关:具体来说,设 i = p 1 a 1 ? p k a k i=p_1^{a_1}\cdots p_k^{a_k} i=p1a1???pkak??,那么 f i f_i fi? 只与可重集 { a i } \{a_i\} {ai?} 有关。

那么我们为每种 { a i } \{a_i\} {ai?} 选一个符合它的最小的数作为代表元(具体来说,将 a i a_i ai? 从大到小排序后,取代表元为 2 a 1 3 a 2 ? 2^{a_1}3^{a_2}\cdots 2a1?3a2??),并只对这些代表元暴力求。

代表元数量很小(实测小于等于 2 × 1 0 7 2\times 10^7 2×107 的代表元只有不到 600 600 600 个,所以对它们每个都根号暴力求都没问题),这样就能做到线性预处理 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32?) 内的前缀和了。

时间复杂度 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32?)

#include<bits/stdc++.h>

#define ll long long

using namespace std;

namespace modular
{
	const int mod=998244353;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
	inline void Add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
	inline void Dec(int &x,int y){x=x-y<0?x-y+mod:x-y;}
	inline void Mul(int &x,int y){x=1ll*x*y%mod;}
}using namespace modular;

inline int poww(int a,ll b)
{
	int ans=1;
	while(b)
	{
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

const int n2=300000,n3=20000000;
const int N2=n2+10,N3=n3+10;

ll n;
int C,K,coef;
int idx,id1[N2],id2[N2];
int cnt,prime[N3],mup[N3],omega[N3],sign[N3];
bool notprime[N3];
int sumf[N2],pref[N3],ff[N3];

int &id(ll x){return x<=n2?id1[x]:id2[n/x];}

void init()
{
	mup[1]=1,omega[1]=0;
	for(int i=2;i<=n3;i++)
	{
		if(!notprime[i])
		{
			prime[++cnt]=i;
			mup[i]=i,omega[i]=1;
		}
		for(int j=1,v;j<=cnt&&(v=i*prime[j])<=n3;j++)
		{
			notprime[v]=1;
			if(!(i%prime[j]))
			{
				mup[v]=mup[i],omega[v]=omega[i];
				break;
			}
			mup[v]=mup[i]*prime[j],omega[v]=omega[i]+1;
		}
	}
	vector<int> sp;
	sp.push_back(1);
	for(int i=1;i<=cnt;i++)
	{
		sp.push_back(sp.back()*prime[i]);
		if(sp.back()>n3) break;
	}
	sign[1]=1,ff[1]=K;
	for(int i=2;i<=n3;i++)
	{
		sign[i]=sign[i/mup[i]]*sp[omega[i]];
		if(i!=sign[i])
		{
			ff[i]=ff[sign[i]];
			continue;
		}
		ff[i]=K;
		for(int j=1;j*j<=i;j++)
		{
			if(!(i%j))
			{
				Add(ff[i],mul(coef,ff[j]));
				if(j>1&&j*j!=i) Add(ff[i],mul(coef,ff[i/j]));
			}
		}
	} 
	for(int i=1;i<=n3;i++) pref[i]=add(pref[i-1],ff[i]);
}

int solve(ll n)
{
	if(n<=n3) return pref[n];
	if(sumf[id(n)]!=-1) return sumf[id(n)];
	int ans=mul(n%mod,K);
	for(ll l=1,r;;l=r+1)
	{
		r=n/(n/l);
		if(r==n) break;
		Add(ans,mul(mul(coef,(n/l-1)%mod),dec(solve(r),solve(l-1))));
	}
	return sumf[id(n)]=ans;
}

int main()
{
	cin>>n>>C;
	if(C==1)
	{
		puts(n<=2?"1":"0");
		return 0;
	}
	K=mul(C,poww(dec(1,C),n-1));
	coef=mul(C,poww(dec(1,C),mod-2));
	for(ll l=1,r;l<=n;l=r+1)
		r=n/(n/l),id(n/l)=++idx;
	init();
	memset(sumf,-1,sizeof(sumf));
	int res=solve(n);
	printf("%d\n",add(poww(dec(1,C),n),res));
	return 0;
}
/*
2 2
*/
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 22:11:31  更:2022-03-11 22:15:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 15:49:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码