您的位置:首页 > 其它

UOJ#272. 【清华集训2016】石家庄的工人阶级队伍比较坚强

2017-10-13 20:55 483 查看

链接:

link

题解:

直接讲构造FWT吧,其他都很简单不想说了。

这里是做3进制异或,考虑分治乘。

T0=A0B0+A1B2+A2B1

T1=A0B1+A1B0+A2B2

T2=A0B2+A1B1+A2B0

如果使用待定系数法,用(A0+xA1+yA2)(B0+xB1+yB2)来构造,那么发现需要满足三个条件:

xy=1,x2=y,y2=x

这提示我们三次单位根。记w表示三次单位根,有:

记Ci=(A0+wiA1+w2iA2)(B0+wiB1+w2iB2),考虑用C构造出T。

注意到w2+w+1=0,

那么(1111ww21w2w)×(1111w2w1ww2)=3I,其中I是单位矩阵。

还有一个问题是w的处理,我们将数表示为a+bw,利用w2=−w−1就可以进行计算了。

这里只需要3在模p意义下有逆元即可,比题目的限制更松了。

代码:

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (;  isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}

const int MAXN = 15;
const int MAXM = 531445;

int n, m, t, mod, pwd[MAXN], cnx[MAXM], cny[MAXM], trans[MAXN][MAXN];

struct Number
{
int x, y;
Number(int _x = 0, int _y = 0) { x = _x, y = _y; }
Number operator + (const Number &b) const { return Number((x + b.x) % mod, (y + b.y) % mod); }
Number operator - (const Number &b) const { return Number((x - b.x + mod) % mod, (y - b.y + mod) % mod); }
Number operator * (const Number &b) const { return Number((1LL * x * b.x - 1LL * y * b.y % mod + mod) % mod, (1LL * x * b.y + 1LL * y * b.x - 1LL * y * b.y % mod + mod) % mod); }
} a[MAXM], b[MAXM];

Number Qow(Number x, int y)
{
Number r(1, 0);
for (; y; y >>= 1, x = x * x)
if (y & 1)
r = r * x;
return r;
}

inline void Exgcd(int a, int b, int &x, int &y)
{
if (!b)
x = 1, y = 0;
else
Exgcd(b, a % b, y, x), y -= a / b * x;
}

inline void DFT(Number *a)
{
Number b[3];
b[0] = a[0] + a[1] + a[2];
b[1] = Number((1LL * a[0].x - a[1].y - a[2].x + a[2].y + (mod << 1)) % mod, (1LL * a[0].y + a[1].x - a[1].y - a[2].x + (mod << 1)) % mod);
b[2] = Number((1LL * a[0].x - a[1].x + a[1].y - a[2].y + (mod << 1)) % mod, (1LL * a[0].y - a[1].x + a[2].x - a[2].y + (mod << 1)) % mod);
a[0] = b[0], a[1] = b[1], a[2] = b[2];
}

inline void IDFT(Number *a)
{
Number b[3];
b[0] = a[0] + a[1] + a[2];
b[2] = Number((1LL * a[0].x - a[1].y - a[2].x + a[2].y + (mod << 1)) % mod, (1LL * a[0].y + a[1].x - a[1].y - a[2].x + (mod << 1)) % mod);
b[1] = Number((1LL * a[0].x - a[1].x + a[1].y - a[2].y + (mod << 1)) % mod, (1LL * a[0].y - a[1].x + a[2].x - a[2].y + (mod << 1)) % mod);
a[0] = b[0], a[1] = b[1], a[2] = b[2];
}

inline void FWT(Number *x, int typ)
{
for (int i = 0; i < m; i ++)
for (int j = 0; j < n; j ++)
if (j / pwd[i] % 3 == 0)
{
Number t[3] = {x[j], x[j + pwd[i]], x[j + (pwd[i] << 1)]};
if (typ)
DFT(t);
else
IDFT(t);
x[j] = t[0], x[j + pwd[i]] = t[1], x[j + (pwd[i] << 1)] = t[2];
}
}

int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
m = Read(), t = Read(), mod = Read();
pwd[0] = 1;
for (int i = 1; i <= m; i ++)
pwd[i] = pwd[i - 1] * 3;
n = pwd[m];
for (int i = 0; i < n; i ++)
a[i].x = Read();
for (int i = 0; i <= m; i ++)
for (int j = 0; i + j <= m; j ++)
trans[i][j] = Read();
for (int i = 0; i < n; i ++)
cnx[i] = cnx[i / 3] + (i % 3 == 1), cny[i] = cny[i / 3] + (i % 3 == 2);
for (int i = 0; i < n; i ++)
b[i].x = trans[cnx[i]][cny[i]];
FWT(a, 0), FWT(b, 0);
for (int i = 0; i < n; i ++)
a[i] = a[i] * Qow(b[i], t);
FWT(a, 1);
int inv, tmp;
Exgcd(n, mod, inv, tmp);
inv = (inv + mod) % mod;
for (int i = 0; i < n; i ++)
printf("%d\n", 1LL * a[i].x * inv % mod);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: