AC日记——「SDOI2017」序列计数 LibreOJ 2002

Posted Only U - IU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC日记——「SDOI2017」序列计数 LibreOJ 2002相关的知识,希望对你有一定的参考价值。

「SDOI2017」序列计数

 

思路:

  矩阵快速幂;

 

代码:

#include <bits/stdc++.h>
using namespace std;
#define mod 20170408
#define ll long long
struct MatrixType {
    int n,m;
    ll ai[105][105];
    void mem(int n_,int m_)
    {
        n=n_,m=m_;
        for(int i=0;i<=n;i++) for(int v=0;v<=m;v++) ai[i][v]=0;
    }
    MatrixType operator*(const MatrixType pos)const
    {
        MatrixType res;res.mem(this->n,pos.m);
        for(int i=0;i<=res.n;i++)
            for(int v=0;v<=res.m;v++)
                for(int x=0;x<=this->m;x++)
                    res.ai[i][v]=(res.ai[i][v]+(this->ai[i][x]*pos.ai[x][v])%mod)%mod;
        return res;
    }
    void debug()
    {
        puts("");
        printf("%d %d\n",n,m);
        for(int i=0;i<=2;i++)
        {
            for(int v=0;v<=2;v++) printf("%d ",this->ai[i][v]);
            putchar(\n);
        }
        puts("");
    }
};
int n,m,p,pi[2000005],cnt,ai[1001],bi[1001];
bool if_p[20000005];
MatrixType poww(MatrixType pos,int mi)
{
    MatrixType res=pos;mi--;
    while(mi)
    {
        if(mi&1) res=res*pos;
        mi=mi>>1,pos=pos*pos;
    }
    return res;
}
void ouler(int lit)
{
    for(int i=2;i<=lit;i++)
    {
        if(!if_p[i]) pi[++cnt]=i;
        for(int j=1;pi[j]*i<=lit&&j<=cnt;j++)
        {
            if_p[i*pi[j]]=true;
            if(i%pi[j]==0) break;
        }
    }
}
int main()
{
    //freopen("ans3.txt","w",stdout);
    scanf("%d%d%d",&n,&m,&p),ouler(m);
    MatrixType sta1;sta1.mem(0,p-1);
    sta1.ai[0][0]=1;
    MatrixType pos1,pos2,ans1,ans2;
    pos1.mem(p-1,p-1),pos2.mem(p-1,p-1);
    for(int i=1;i<=m;i++) ai[i%p]++;
    for(int i=0;i<p;i++) bi[i]=ai[i];
    for(int i=1;i<=cnt;i++) bi[pi[i]%p]--;
    for(int i=0;i<p;i++)
    {
        for(int v=0;v<p;v++)
        {
            if(i>v) pos1.ai[i][v]=ai[i-v],pos2.ai[i][v]=bi[i-v];
            if(i==v) pos1.ai[i][v]=ai[0],pos2.ai[i][v]=bi[0];
            if(i<v) pos1.ai[i][v]=ai[p-v+i],pos2.ai[i][v]=bi[p-v+i];
        }
    }
    pos1=poww(pos1,n),pos2=poww(pos2,n);
    ans1=sta1*pos1,ans2=sta1*pos2;
    cout<<(ans1.ai[0][0]-ans2.ai[0][0]+mod)%mod;
    return 0;
}

 

以上是关于AC日记——「SDOI2017」序列计数 LibreOJ 2002的主要内容,如果未能解决你的问题,请参考以下文章

LibreOJ #2002. 「SDOI2017」序列计数

[Sdoi2017]序列计数

BZOJ4818: [Sdoi2017]序列计数

[SDOI2017]序列计数

P3702 [SDOI2017]序列计数

[SDOI2017]序列计数