JZOJ6915. 显示器(display)
题目大意

解题思路
第一部分:
考虑一个\(k\)步的转移,即从一个\(m\)位整数转移到另一个,那么这个东西可以通过\(O(2^{5m}\log{k})\)的时间通过倍增优化dp求出.
具体地,设\(f_{2^i,S}\)表示改变了\(2^i\)次灯管的状态能够到达灯管的状态为\(S\)的方案数, 那么一次转移实质上是一次异或卷积. 由于不会给了4秒,所以不用FWT,直接暴力卷积,倍增优化即可.
当求出了这个东西之后, 整个\(n\)步的转移就被分割成了\(\lfloor\frac{n}{k}\rfloor\)次长度为\(k\)的转移和一次长度为\(n\mod{k}\)的转移.
对于前面的一部分,即第二部分,使用矩阵快速幂, 在\(O((10^m)^3\log{\lfloor\frac{n}{k}\rfloor})\)的时间内解决.
具体地,利用前面dp的结果可以构造出初始矩阵. 一次矩阵乘法也相当于一次转移. 不再细说.
对于后面的一部分,即第三部分, 可以与第一部分相类似的方法求解.
#include <cstdio>
#include <cstring>
#define N 110
#define ll long long
#define rg register
#define MOD 1000000007
#define init(a, b) memset(a, b, sizeof(a))
#define fo(i, a, b) for(int i = (a); i <= (b); ++i)
#define fd(i, a, b) for(int i = (a); i >= (b); --i)
using namespace std;
int m, x, p[3] = {1, 9, 99}, q[3] = {1, 31, 1023}, pr[100] = {10, 2, 9, 7, 18, 21, 12, 3, 29, 23}, w[1024];
ll n, k;
struct Mat
{
int a[N][N];
Mat(){init(a, 0);}
int* operator[] (const int x) {return a[x];}
Mat operator*(Mat y) const
{
Mat z;
fo(i, 0, p[m])
fo(k, 0, p[m])
{
rg int t = a[i][k];
if(!t) continue ;
fo(j, 0, p[m])
z[i][j] = (z[i][j] + 1ll * a[i][k] * y[k][j]) % MOD;
}
return z;
}
}ans1, p1;
struct Poly
{
int a[1 << 10];
Poly(){init(a, 0);}
int& operator[](const int x){return a[x];}
Poly operator*(Poly y) const
{
Poly z;
fo(i, 0, q[m])
fo(j, 0, q[m])
z[i ^ j] = (z[i ^ j] + 1ll * a[i] * y[j]) % MOD;
return z;
}
}ans2, p2;
template<typename T>
inline void qpow(T &p, T a, ll b){for(; b; b >>= 1, a = a * a) b & 1 && (p = p * a, 1);}
inline void pre()
{
if(m == 2)
{
fo(i, 10, 99) pr[i] = pr[i % 10] + (pr[i / 10] << 5);
fo(i, 0, 9) pr[i] += 10 << 5;
}
fo(i, 0, q[m]) w[i] = -1;
fo(i, 0, p[m]) w[pr[i]] = i;
fo(i, 1, m * 5) p2[1 << (i - 1)] = 1;
}
int main()
{
freopen("display.in", "r", stdin);
freopen("display.out", "w", stdout);
scanf("%d %lld %lld %d", &m, &n, &k, &x);
pre();
ans2[0] = 1; qpow(ans2, p2, k);
fo(i, 0, p[m]) fo(j, 0, p[m]) p1[i][j] = ans2[pr[i] ^ pr[j]];
fo(i, 0, q[m])
if(w[i ^ pr[x]] >= 0)
ans1[0][w[i ^ pr[x]]] = ans2[i];
qpow(ans1, p1, n / k - 1);
fo(i, 0, q[m]) ans2[i] = 0;
fo(i, 0, p[m]) ans2[pr[i]] = ans1[0][i];
qpow(ans2, p2, n % k);
fo(i, 0, p[m]) printf("%d\n", ans2[pr[i]]);
return 0;
}
浙公网安备 33010602011771号