zoukankan      html  css  js  c++  java
  • 单位根反演学习笔记

    单位根反演学习笔记

    公式

    ([n|a]=dfrac{1}{n}sumlimits_{k=0}^{n-1}w_n^{ak})

    (a=0 pmod n) 时,(w_n^{ak}=1),所以该式的值为 (1)

    (a e 0 pmod n) 时,根据等比数列的求和公式,

    原式 (=dfrac{1}{n}sumlimits_{k=0}^{n-1}w_n^{ak}=dfrac{1}{n}dfrac{w_n^{an}-1}{w_n^a-1})

    分子部分的值为 (0),所以整个式子的值为 (0)

    也可以推导出下面的形式:

    ([a=bpmod n]=[a-b=0pmod n]=dfrac{1}{n}sumlimits_{i=0}^{n-1}w_n^{(a-b)k}=dfrac{1}{n}sumlimits_{i=0}^{n-1}w_n^{ak}w_n^{-bk})

    应用

    P5591 小猪佩奇学数学

    题目描述

    给定 (n,p,k),求

    [sumlimits_{i=0}^n inom n i imes p^{i} imes leftlfloor dfrac{i}{k} ight floor mod 998244353 ,1 leq n,p <998244353,k in {2^{w}|0 leq w leq 20} ]

    分析

    (k) 的范围给的很有特点,不难猜出是单位根反演。

    发现 (leftlfloor dfrac{i}{k} ight floor =(sum_{j=0}^i[k|j])-1),

    带入原式,有

    (egin{aligned}sumlimits_{i=0}^n inom n i p^{i} ((sum_{j=0}^i[k|j])-1)&=sumlimits_{i=0}^n inom n i p^{i} ((sum_{j=0}^ifrac{1}{k}sum_{d=0}^{k-1}w_k^{dj})-1)\&= sumlimits_{i=0}^n inom n i p^{i} sum_{j=0}^ifrac{1}{k}sum_{d=0}^{k-1}w_k^{dj}-sum_{i=0}^ninom n ip^i\ &=frac{1}{k}sum_{d=0}^{k-1}sum_{i=0}^ninom n i p^isum_{j=0}^i w_k^{dj}-(p+1)^n\ end{aligned})

    后面的部分可以用等比数列求和公式计算,但是要求公比不能为一,所以要特判 (d=0) 的情况。

    (egin{aligned}frac{1}{k}sum_{d=0}^{k-1}sum_{i=0}^ninom n i p^isum_{j=0}^i w_k^{dj}-(p+1)^n &=frac{1}{k}sum_{d=1}^{k-1}sum_{i=0}^ninom n i p^ifrac{w_k^{d(i+1)}-1}{w_k^d-1}-(p+1)^n + frac{1}{k}sum_{i=0}^n inom n i p^i (i+1) \ &=frac{1}{k}sum_{d=1}^{k-1}frac{sum_{i=0}^ninom n i p^i(w_k^{d(i+1)}-1)}{w_k^d-1}-(p+1)^n+frac{1}{k}sum_{i=0}^n inom n ip^i i+frac{1}{k}sum_{i=0}^n inom n ip^i \ &=frac{1}{k}sum_{d=1}^{k-1}frac{sum_{i=0}^ninom n i p^iw_k^{d(i+1)}-sum_{i=0}^ninom n i p^i}{w_k^d-1}-(p+1)^n+frac{1}{k}sum_{i=0}^n inom {n-1}{i-1} n p^i+frac{1}{k}(p+1)^n \&=frac{1}{k}sum_{d=1}^{k-1}frac{w_k^dsum_{i=0}^ninom n i (pw_k^d)^i-(p+1)^n}{w_k^d-1}-(p+1)^n+frac{1}{k}np(p+1)^{n-1}+frac{1}{k}(p+1)^n \&=frac{1}{k}sum_{d=1}^{k-1}frac{w_k^d(pw_k^d+1)^n-(p+1)^n}{w_k^d-1}-(p+1)^n+frac{1}{k}np(p+1)^{n-1}+frac{1}{k}(p+1)^n \ end{aligned})

    这个东西就可以在 (klogn) 的时间复杂度内计算。

    这道题中单位根的带换和二项式定理的使用是很巧妙的。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=2e6+5,mod=998244353,G=3;
    inline int addmod(rg int now1,rg int now2){
    	return now1+=now2,now1>=mod?now1-mod:now1;
    }
    inline int delmod(rg int now1,rg int now2){
    	return now1-=now2,now1<0?now1+mod:now1;
    }
    inline int mulmod(rg long long now1,rg int now2){
    	return now1*=now2,now1>=mod?now1%mod:now1;
    }
    int ksm(rg int ds,rg int zs){
    	rg int nans=1;
    	while(zs){
    		if(zs&1) nans=mulmod(nans,ds);
    		ds=mulmod(ds,ds);
    		zs>>=1;
    	}
    	return nans;
    }
    int n,p,k,ans,wn;
    int main(){
    	read(n),read(p),read(k);
    	wn=ksm(G,(mod-1)/k);
    	rg int tmp1,tmp2;
    	for(rg int d=1;d<=k-1;d++){
    		tmp1=ksm(wn,d);
    		tmp2=mulmod(tmp1,ksm(addmod(mulmod(tmp1,p),1),n));
    		tmp2=delmod(tmp2,ksm(p+1,n));
    		tmp2=mulmod(tmp2,ksm(delmod(tmp1,1),mod-2));
    		ans=addmod(ans,tmp2);
    	}
    	ans=mulmod(ans,ksm(k,mod-2));
    	ans=delmod(ans,ksm(p+1,n));
    	ans=addmod(ans,mulmod(ksm(k,mod-2),mulmod(n,mulmod(p,ksm(p+1,n-1)))));
    	ans=addmod(ans,mulmod(ksm(k,mod-2),ksm(p+1,n)));
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Linux route
    python 实现自定义切片类
    python 自省机制
    python 实例方法、静态方法、类方法
    python 动态语言和协议编程
    python 鸭子类型
    信息论
    CRF keras代码实现
    CRF 详细推导、验证实例
    attention 汇总(持续)
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/14590060.html
Copyright © 2011-2022 走看看