Codeforces 691E Xor-sequences
矩阵快速幂。递推式:dp[k][i]=sum(dp[k-1][j]*f[i][j]),dp[k][i]表示的意义是序列中有k个元素,最后一个元素是i的方案数,f[i][j]=1表示i与j能放在一起,反之表示不能放在一起。因为k较大,所以可以构造矩阵进行加速。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi = acos(-1.0), eps = 1e-8; void File() { freopen("D:\\in.txt", "r", stdin); freopen("D:\\out.txt", "w", stdout); } inline int read() { char c = getchar(); while (!isdigit(c)) c = getchar(); int x = 0; while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x; } int n; LL k,a[105],mod=1e9+7;; struct Matrix { long long A[105][105]; int R, C; Matrix operator*(Matrix b); }; Matrix X, Y, Z; Matrix Matrix::operator*(Matrix b) { Matrix c; memset(c.A, 0, sizeof(c.A)); int i, j, k; for (i = 1; i <= R; i++) for (j = 1; j <= C; j++) for (k = 1; k <= C; k++) c.A[i][j] = (c.A[i][j] + (A[i][k] * b.A[k][j])%mod)%mod; c.R=R; c.C=b.C; return c; } int check(LL x) { int sz=0; while(x) { if(x%2==1) sz++; x=x/2; } if(sz%3==0) return 1; return 0; } void init() { memset(X.A,0,sizeof X.A); memset(Y.A,0,sizeof Y.A); memset(Z.A,0,sizeof Z.A); Z.R = 1; Z.C = n; for(int i=1;i<=n;i++) Z.A[1][i]=Y.A[i][i]=1; Y.R = n; Y.C = n; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) X.A[i][j]=X.A[j][i]=check(a[i]^a[j]); X.R=n; X.C=n; } void work() { k--; while (k) { if (k % 2 == 1) Y = Y*X; k = k >> 1,X = X*X; } Z = Z*Y; LL ans=0; for(int i=1;i<=n;i++) ans=(ans+Z.A[1][i])%mod; printf("%lld\n", ans); } int main() { scanf("%d%lld",&n,&k); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); init(); work(); return 0; }