题目分析

题意转化为,有 $n$个数的序列,每个数你可以让它为一个 $[1,m]$之间的取值,问任意连续 $K$个数都线性无关的序列总数。

设 $m+1=2^c$

那么若 $K>c$,因为若 $K$个数线性相关,那么它们一定可以通过异或的方式生成 $2^K$个不同的数,所以这种情况下任意 $K$个连续的数一定线性无关,答案就是 $m^n$

若 $K \leq c$,考虑统计存在 $K$个连续的数线性相关的序列数 $ans$,最终答案就是 $m^n-ans$。设 $f(i,j)$表示放了 $i$个数,后 $j$个数线性相关。

假设新添加的数与这 $j$个数都线性相关,则一定是这 $j$个数可以生成的 $2^j$个数以外的数,所以 $f(i,j+1)+=(m-2^j)f(i,j)$

假设新添加的数与后 $t(t<j)$个数线性相关,而加上从后往前数的第 $t+1$个数后,就线性无关了。那么这个数一定是后 $t$个数生成的 $2^t$个数中的某个与第 $t+1$个数异或的结果,所以 $f(i,t+1)+=2^tf(i,j)$

对于每一个 $i$,$ans+=f(i,K)m^{n-i}$

可以矩阵快速幂,但是 $f(i,K)m^{n-i}$比较难处理。将答案看做一个关于 $m$的多项式,用秦九韶定理后,可以表示为:

$…(((f(0,K)m+f(1,K))m+f(2,K))m+f(3,K))m…$

就可以用矩阵处理了。

代码

#include<bits/stdc++.h>
using namespace std;
#define RI register int
const int mod=1000000007;
int n,m,K,c,bin[30];
struct matrix{int t[30][30];}X,re;

int qm(int x) {return x>=mod?x-mod:x;}
int ksm(int x,int y) {
    int re=1;
    for(;y;y>>=1,x=1LL*x*x%mod) if(y&1) re=1LL*re*x%mod;
    return re;
}
matrix operator * (matrix A,matrix B) {
    matrix C;
    for(RI i=0;i<=K;++i)
        for(RI j=0;j<=K;++j) C.t[i][j]=0;
    for(RI k=0;k<=K;++k)
        for(RI i=0;i<=K;++i)
            for(RI j=0;j<=K;++j)
                C.t[i][j]=qm(C.t[i][j]+1LL*A.t[i][k]*B.t[k][j]%mod);
    return C;
}

class YetAnotherNim{
    public:
    int solve(int kn,int km,int kK) {
        n=kn,m=km,K=kK;
        for(RI i=m+1;i!=1;i>>=1) ++c;
        if(K>c) return ksm(m,n);
        bin[0]=1;for(RI i=1;i<=c;++i) bin[i]=bin[i-1]<<1;
        for(RI i=1;i<K;++i) {
            for(RI j=0;j<i;++j) X.t[j+1][i]=bin[j];
            X.t[i+1][i]=m+1-bin[i];
        }
        X.t[0][K]=1,X.t[0][0]=m;
        for(RI i=0;i<=K;++i) re.t[i][i]=1;
        for(RI i=n;i;i>>=1,X=X*X) if(i&1) re=re*X;
        return qm(ksm(m,n)-1LL*m*re.t[0][1]%mod+mod);
    }
};
分类: 文章

litble

苟...苟活者在淡红的血色中,会依稀看见微茫的希望

1 条评论

boshi · 2019年2月22日 4:20 下午

其实不需要什么秦九韶,只需要保证”k 个线性无关” 只能转移到”k 个线性无关” 就行了。也就是说只要存在有 k 个,后面填什么它都还是 k 个。

发表评论

电子邮件地址不会被公开。 必填项已用*标注