MnZn求助矩阵乘法
查看原帖
MnZn求助矩阵乘法
420129
Nt_Tsumiki楼主2024/8/12 16:29

rt,第二个样例过不去

想法是把贡献展开算。

#include <iostream>
#include <cstring>
#include <cstdio>

#define LL long long
#define MOD 998244353

using namespace std;
LL n; int m,a[25][25];

int pcnt,p[25],vis[25];

void euler() {
    for (int i=2;i<=m;i++) {
        if (!vis[i]) p[++pcnt]=i;
        for (int j=1;j<=pcnt and i*p[j]<=m;j++) {
            vis[i*p[j]]=1;
            if (i%p[j]==0) break;
        }
    }
}

struct Matrix {
    LL a[64][64];

    Matrix() { memset(a,0,sizeof a); }
    LL *operator[](int x) { return a[x]; }
    Matrix operator*(Matrix &B) {
        Matrix C;
        for (int i=0;i<(1<<pcnt);i++)
            for (int j=0;j<(1<<pcnt);j++)
                for (int k=0;k<(1<<pcnt);k++)
                    (C[i][j]+=a[i][k]*B[k][j]%MOD)%=MOD;
        return C;
    }
}A,E;

Matrix quickpow(Matrix &a,LL k) {
    Matrix res; for (int i=0;i<(1<<pcnt);i++) res[i][i]=1;
    while (k) {
        if (k&1) res=res*a;
        a=a*a,k>>=1;
    }
    return res;
}

int main() {
    scanf("%lld%d",&n,&m);
    euler();
    for (int i=1;i<=m;i++) {
        int tmp=i;
        for (int j=1;j<=pcnt;j++)
            if (tmp%p[j]==0)
                while (tmp%p[j]==0) a[i][j]++,tmp/=p[j];
    }
    for (int i=1;i<=m;i++) {
        for (int j=0;j<(1<<pcnt);j++) {
            for (int k=0;k<(1<<pcnt);k++) {
                bool flag=0;
                for (int l=1;l<=pcnt;l++)
                    if (((j>>(l-1))&1) and ((k>>(l-1))&1)==0) { flag=1; break; }
                if (flag) continue;
                LL mul=1;
                for (int l=1;l<=pcnt;l++)
                    if (((j>>(l-1))&1)==0 and ((k>>(l-1))&1))
                        mul=mul*a[i][l]%MOD;
                (A[j][k]+=mul)%=MOD;
            }
        }
    }
    for (int i=0;i<(1<<pcnt);i++) E[0][i]=1;
    A=quickpow(A,n); E=E*A;
    printf("%lld\n",E[0][(1<<pcnt)-1]);
    return 0;
}
2024/8/12 16:29
加载中...