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

    ##### 基本柿子

    $$
    frac{1}{n} sum_{i=0}^{n-1} w_n^{ki} = [n|k]
    $$

    证明如下:

    1.当$n|k$时,设$k=np$。

    $frac{1}{n} sum_{i=0}^{n-1} w_{n}^{npi} = frac{1}{n} sum_{i=0}^{n-1} w_{n}^{0} = 1$

    2.当$n mid k$时

    $frac{1}{n} frac{w_n^{nk}-w_{n}^0}{w_n^k-1}=0$

    ##### 例题

    BZOJ PYXFIB

    $sum_{i=0}^n inom{n}{i} F_i [i\%d==0]$

    $ frac{1}{d} sum_{i=0}^n inom{n}{i} F_i sum_{j=0}^{d-1} w_d^{ij}$

    显然$F$要用矩乘加速

    然后把$w_d^j$直接扔进去好了x

    最后就是$frac{1}{d}(w_n^j F + I)^n$

    代码

    //Love and Freedom.
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define inf 20021225
    using namespace std;
    ll read()
    {
        ll s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    struct mat
    {
        int a[2][2];
        mat(){}
        mat(int lu,int ru,int ld,int rd){a[0][0]=lu,a[0][1]=ru,a[1][0]=ld,a[1][1]=rd;}
        void clear(){memset(a,0,sizeof(a));}
        void det(){clear(); a[0][0]=a[1][1]=1;}
    };
    int G,mdn;
    void upd(int &x,int y){x+=x+y>=mdn?y-mdn:y;}
    mat operator+(mat a,mat b)
    {
        mat tmp;
        for(int i=0;i<2;i++)    for(int j=0;j<2;j++)
            tmp.a[i][j]=(a.a[i][j]+b.a[i][j])%mdn; 
        return tmp;
    }
    mat operator*(mat a,mat b)
    {
        mat tmp; tmp.clear();
        for(int i=0;i<2;i++)    for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)    upd(tmp.a[i][j],1ll*a.a[i][k]*b.a[k][j]%mdn);
        return tmp;
    }
    int fac[211],tot; 
    int ksm(int bs,int mi)
    {
        int ans=1;
        while(mi)
        {
            if(mi&1)    ans=1ll*ans*bs%mdn;
            bs=1ll*bs*bs%mdn; mi>>=1;
        }
        return ans;
    }
    void getG()
    {
        int top=mdn-1; tot=0;
        for(int i=1;i<=sqrt(top);i++)
            if(top%i==0)    fac[++tot]=i,fac[++tot]=top/i;
        for(G=2;G<=100;G++)
        {
            int i;
            for(i=1;i<=tot;i++)    if(fac[i]!=top&&ksm(G,fac[i])==1)    break;
            if(i>tot)    return;
        }
    }
    mat mksm(mat bs,ll mi)
    {
        mat ans; ans.det();
        while(mi)
        {
            if(mi&1)    ans=ans*bs;
            bs=bs*bs; mi>>=1;
        }
        return ans;
    }
    int main()
    {
        int T=read();
        while(T--)
        {
            ll n=read(),k=read(); mdn=read(); getG(); int Wn=ksm(G,(mdn-1)/k); int ans=0;
            for(int i=0;i<k;i++)
            {
                int w=ksm(Wn,i); mat cur=mksm(mat(w+1,w,w,1),n);
                int val=cur.a[0][0];
                upd(ans,val);
            }
            printf("%d
    ",1ll*ans*ksm(k,mdn-2)%mdn);
        }
        return 0;
    }
    View Code

    LOJ6485. LJJ 学二项式定理

    $frac{1}{4}sum_{i=0}^n sum_{j=0}^3 a_j s^i inom{n}{i} [i\%4==j]$

    $frac{1}{4}sum_{i=0}^nsum_{j=0}^3 a_j s^iinom{n}{i} [(i-j)\%4==0]$

    $frac{1}{4}sum_{i=0}^nsum_{j=0}^3 a_j s^iinom{n}{i} sum_{k=0}^3 w_4^{(i-j)k}$

    $frac{1}{4}sum_{j=0}^3 a_j sum_{i=0}^n s^i inom{n}{i} sum_{k=0}^3 w_{4}^{(i-j)k}$

    $frac{1}{4}sum_{j=0}^3 sum_{k=0}^3 a_j w^{-jk}(sw_{4}^k+1)^n$

    然后就做完惹

    //Love and Freedom.
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define inf 20021225
    #define mdn 998244353
    #define G 3
    #define inv4 748683265
    using namespace std;
    ll read()
    {
        ll s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    int ksm(int bs,ll mi)
    {
        int ans=1;
        while(mi)
        {
            if(mi&1)    ans=1ll*ans*bs%mdn;
            bs=1ll*bs*bs%mdn; mi>>=1; 
        }
        return ans;
    }
    int a[4];
    int main()
    {
        int Wn=ksm(G,(mdn-1)/4);
        int T=read();
        while(T--)
        {
            ll n=read(); int s=read(); int ans=0;
            for(int i=0;i<4;i++)
            {
                int w=Wn,cur=0; a[i]=read();
                for(int j=0,k=1;j<4;j++,k=1ll*k*w%mdn)
                    (cur+=1ll*ksm(1ll*s*k%mdn+1,n)*ksm(k,4-i)%mdn*inv4%mdn)%=mdn;
                (ans+=1ll*cur*a[i]%mdn)%=mdn;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    mysql左连接、右链接、内连接
    各种排序算法及其java程序实现(转载)
    将Android手机设备挂载到ubuntu中
    EditText 不让其自动获取焦点
    Ubuntu安装JDK+Tomcat+Eclipse以及Android adb配置环境变量
    ADT22解决引用第三方jar提示java.lang.NoClassDefFoundError
    winform实现类似google的搜索提示Suggest Search
    抽象工厂模式
    各种小知识随笔
    CSS知识点【待整理】
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/12033200.html
Copyright © 2011-2022 走看看