HDU5730 Shell Necklace
Posted xgzc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5730 Shell Necklace相关的知识,希望对你有一定的参考价值。
题面
题意简述
一段长为(i)的项链有(a_i)中装饰方法,问长度为(n)的项链有多少种装饰方式。
答案对(313)取膜
题解
设(f[i])表示(mathcal{DP})到第(i)位有多少种方式
[
f[i] = sum_{j=1}^{i-1} f[j]a[i - j]
]
分治(mathcal{FFT})走起
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))
inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
}
const int maxn(3e5 + 10), Mod(313);
const double pi(acos(-1));
struct complex { double x, y; };
inline complex operator + (const complex &lhs, const complex &rhs)
{ return (complex) {lhs.x + rhs.x, lhs.y + rhs.y}; }
inline complex operator - (const complex &lhs, const complex &rhs)
{ return (complex) {lhs.x - rhs.x, lhs.y - rhs.y}; }
inline complex operator * (const complex &lhs, const complex &rhs)
{
return (complex) {lhs.x * rhs.x - lhs.y * rhs.y,
lhs.y * rhs.x + lhs.x * rhs.y};
}
template<int opt> void FFT(complex *p, int n)
{
for(RG int i = 1; i < n; i <<= 1)
{
complex rot = (complex) {cos(pi / i), opt * sin(pi / i)};
for(RG int j = 0; j < n; j += (i << 1))
{
complex w = (complex) {1, 0};
for(RG int k = 0; k < i; ++k, w = w * rot)
{
complex x = p[j + k], y = w * p[i + j + k];
p[j + k] = x + y, p[i + j + k] = x - y;
}
}
}
}
void Mul(int n1, int n2, complex *a, complex *b, complex *c)
{
static int n, m, r[maxn], P;
for(m = n1 + n2, n = 1, P = -1; n <= m; n <<= 1, ++P);
for(RG int i = n1; i < n; i++) a[i].x = a[i].y = 0.;
for(RG int i = n2; i < n; i++) b[i].x = b[i].y = 0.;
for(RG int i = 0; i < n; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << P);
for(RG int i = 0; i < n; i++)
if(i < r[i]) std::swap(a[i], a[r[i]]), std::swap(b[i], b[r[i]]);
FFT<1>(a, n), FFT<1>(b, n);
for(RG int i = 0; i < n; i++) c[i] = a[i] * b[i];
for(RG int i = 0; i < n; i++) if(i < r[i]) std::swap(c[i], c[r[i]]);
FFT<-1>(c, n);
for(RG int i = 0; i < n; i++) c[i].x = c[i].x / n + .5;
}
int f[maxn], a[maxn], n;
void CDQ(int l, int r)
{
static complex A[maxn], B[maxn], C[maxn];
if(l == r) return (void) (f[l] = (f[l] + a[l]) % Mod);
int mid = (l + r) >> 1; CDQ(l, mid);
for(RG int i = l; i <= mid; i++) A[i - l].x = f[i], A[i - l].y = 0.;
for(RG int i = 1; i <= r - l; i++) B[i - 1].x = a[i], B[i - 1].y = 0.;
Mul(mid - l + 1, r - l, A, B, C);
for(RG int i = mid + 1; i <= r; i++)
f[i] = (f[i] + (int)C[i - (l + 1)].x) % Mod;
CDQ(mid + 1, r);
}
int main()
{
while(~scanf("%d", &n))
{
if(!n) break; clear(f, 0), f[0] = 1;
for(RG int i = 1; i <= n; i++) a[i] = read() % Mod;
CDQ(1, n); printf("%d
", f[n]);
}
return 0;
}
以上是关于HDU5730 Shell Necklace的主要内容,如果未能解决你的问题,请参考以下文章
HDU5730 Shell Necklace(DP + CDQ分治 + FFT)
hdu 5730 Shell Necklace ?????? ??????FFT
HDU 5730 Shell Necklace(CDQ分治+FFT)