hdu 5730 Shell Necklace —— 分治FFT

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5730

DP式:\( f[i] = \sum\limits_{j=1}^{i} f[i-j] * a[j] \)

因为没有给 \( f[0] \) 赋初值,所以在递归底层令 \( f[l] += a[l] \)

注意多组数据清空数组;

读入 \( s[i] \) 时要取模!!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
typedef double db;
int const xn=(1<<18),mod=313;
db const Pi=acos(-1.0);
int n,rev[xn],f[xn],s[xn];
struct cpl{
  db x,y;
  cpl(db xx=0,db yy=0):x(xx),y(yy) {}
}a[xn],b[xn];
cpl operator + (cpl a,cpl b){return cpl(a.x+b.x,a.y+b.y);}
cpl operator - (cpl a,cpl b){return cpl(a.x-b.x,a.y-b.y);}
cpl operator * (cpl a,cpl b){return cpl(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=0; ch=getchar();}
  while(ch>=‘0‘&&ch<=‘9‘)ret=ret*10+ch-‘0‘,ch=getchar();
  return f?ret:-ret;
}
void fft(cpl *a,int tp,int lim)
{
  for(int i=0;i<lim;i++)
    if(i<rev[i])swap(a[i],a[rev[i]]);
  for(int mid=1;mid<lim;mid<<=1)
    {
      cpl wn=cpl(cos(Pi/mid),tp*sin(Pi/mid));
      for(int j=0,len=(mid<<1);j<lim;j+=len)
    {
      cpl w=cpl(1,0);
      for(int k=0;k<mid;k++,w=w*wn)
        {
          cpl x=a[j+k],y=w*a[j+mid+k];
          a[j+k]=x+y; a[j+mid+k]=x-y;
        }
    }
    }
  if(tp==1)return;
  for(int i=0;i<lim;i++)a[i].x=a[i].x/lim;
}
int upt(int x){while(x>=mod)x-=mod; while(x<0)x+=mod; return x;}
void work(int l,int r)
{
  if(l==r){f[l]=upt(f[l]+s[l]); return;}//f[0]=0...
  int len=r-l+1,mid=((l+r)>>1);
  work(l,mid);
  int lim=1,L=0;
  while(lim<len)lim<<=1,L++;
  for(int i=0;i<lim;i++)rev[i]=((rev[i>>1]>>1)|((i&1)<<(L-1)));
  for(int i=l;i<=mid;i++)a[i-l].x=f[i],a[i-l].y=0;//y
  for(int i=mid-l+1;i<lim;i++)a[i].x=0,a[i].y=0;
  for(int i=0;i<lim;i++)b[i].x=s[i],b[i].y=0;
  fft(a,1,lim); fft(b,1,lim);
  for(int i=0;i<lim;i++)a[i]=a[i]*b[i];
  fft(a,-1,lim);
  for(int i=mid+1;i<=r;i++)f[i]+=(ll)(a[i-l].x+0.5)%mod;
  work(mid+1,r);
}
int main()
{
  while(1)
    {
      n=rd(); if(!n)return 0;
      memset(f,0,sizeof f); memset(s,0,sizeof s);
      for(int i=1;i<=n;i++)s[i]=rd()%mod;//%mod!!
      work(1,n);
      printf("%d\n",f[n]);
    }
}

原文地址:https://www.cnblogs.com/Zinn/p/10057140.html

时间: 2024-10-16 07:35:57

hdu 5730 Shell Necklace —— 分治FFT的相关文章

HDU 5730 Shell Necklace(CDQ分治+FFT)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3,则其权值为5,现在有长度为n的字段,求通过不同拆分得到的字段权值乘积和. [题解] 记DP[i]表示长度为i时候的答案,DP[i]=sum_{j=0}^{i-1}DP[j]w[i-j],发现是一个卷积的式子,因此运算过程可以用FFT优化,但是由于在计算过程中DP[j]是未知值,顺次计算复杂度是O(

hdu 5730 Shell Necklace fft+cdq分治

题目链接 dp[n] = sigma(a[i]*dp[n-i]), 给出a1.....an, 求dp[n]. n为1e5. 这个式子的形式显然是一个卷积, 所以可以用fft来优化一下, 但是这样也是会超时的. 所以可以用cdq分治来优化. cdq分治就是处理(l, mid)的时候, 将dp[l]...dp[mid]对dp[mid+1]...dp[r]做的贡献都算出来. #include <bits/stdc++.h> using namespace std; #define pb(x) pus

HDU 5730 - Shell Necklace

题意: 给出连续的1-n个珠子的涂色方法 a[i](1<=i<=n), 问长度为n的珠链共有多少种涂色方案 分析: 可以得到DP方程: DP[n] = ∑(i=1,n) (DP[n-i]*a[i]). 该方程为卷积形式,故 CDQ + FFT CDQ: 将 [l,r] 二分, 先得到[l,mid]的答案,再更新[l,mid]对[mid+1,r]的贡献.   对任意 DP[j](mid+1 <= j <= r), [l,mid] 对其贡献为 ∑(i=l,mid) (DP[i]*a[j

HDU Shell Necklace CDQ分治+FFT

Shell Necklace Problem Description Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklace with n beautiful shells contains the most sincere feeling for my best lover Arrietty, but even that is not enough. Suppose

HDU5730 Shell Necklace(DP + CDQ分治 + FFT)

题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5730 Description Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklace with n beautiful shells contains the most sincere feeling for my best lover Arrietty, but

hdu5730 Shell Necklace 【分治fft】

题目 简述: 有一段长度为n的贝壳,将其划分为若干段,给出划分为每种长度的方案数,问有多少种划分方案 题解 设\(f[i]\)表示长度为\(i\)时的方案数 不难得dp方程: \[f[i] = \sum\limits_{j=0}^{i} a[j] * f[i - j]\] 考虑转移 直接转移是\(O(n^2)\)的 如何优化? 容易发现这个转移方程非常特别,是一个卷积的形式 考虑fft 分治fft 分治fft解决的就是这样一个转移方程的快速计算的问题 \[f[i] = \sum\limits_{

HDU5730 Shell Necklace

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 999    Accepted Submission(s): 434 Problem Description Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklac

2016 Multi-University Training Contest 1 H.Shell Necklace

Shell Necklace Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 534    Accepted Submission(s): 227 Problem Description Perhaps the sea‘s definition of a shell is the pearl. However, in my view,

2017 3 11 分治FFT

考试一道题的递推式为$$f[i]=\sum_{j=1}^{i} j^k \times (i-1)! \times \frac{f[i-j]}{(i-j)!}$$这显然是一个卷积的形式,但$f$需要由自己卷过来(我也不知到怎么说),以前只会生成函数的做法,但这题好像做不了(谁教教我怎么做),于是无奈的写了一发暴力,看题解发现是分治FFT.分治每层用$f[l]-f[mid]$与$a[1]-a[r-l]$做NTT.这样显然每个$f[l]-f[mid]$对$f[mid+1]-f[r]$的贡献都考虑到了.