BZOJ3160【万径人踪灭】 【FFT】

2023-11-10 21:40
文章标签 fft 万径 人踪 bzoj3160

本文主要是介绍BZOJ3160【万径人踪灭】 【FFT】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

。。恩 打了四五遍 不会也背出来了。。

BZOJ3160 【听说时限紧?转C++的优势么?】

上AC代码 fft

 1 /*Problem: 3160
 2     User: cyz666
 3     Language: C++
 4     Result: Accepted
 5     Time:1992 ms
 6     Memory:18492 kb
 7 ****************************************************************/
 8  
 9 #include <bits/stdc++.h>
10 #define LL long long
11 const LL mo=1000000007;
12 const double pi=acos(-1.0);
13 using namespace std;
14 struct cp{
15     double x,y;
16     cp(double a=0,double b=0):x(a),y(b){}
17     //cp(double a=0,double b=0){x=a,y=b;}
18 }a[400005],b[400005],W[200005];
19 int h[400005],rev[400005],f[200005],c[200005],n,x,m; 
20 char s; LL ans;
21 cp operator +(cp a,cp b){
22     cp c(a.x+b.x,a.y+b.y);
23     return c;
24 }
25 cp operator *(cp a,cp b){
26     cp c(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
27     return c;
28 }
29 cp operator -(cp a,cp b){
30     return (cp){a.x-b.x,a.y-b.y};
31 }
32 void fft(cp a[],int n,int d=1){
33     if (d<0) reverse(a+1,a+n);
34     for (int i=0;i<n;++i)
35         if (i<rev[i]) swap(a[i],a[rev[i]]);
36     for (int i=0;i<n/2;++i)
37         W[i]=cp(cos(2*pi/n*i),sin(2*pi/n*i));
38     for (int m=2,k=1;m<=n;k=m,m<<=1)
39         for (int i=0;i<n;i+=m)
40         for (int j=i;j<i+k;++j){
41             cp u=a[j],v=a[j+k]*W[n/m*(j-i)];
42             a[j]=u+v,a[j+k]=u-v;
43         }
44     if (d<0) for (int i=0;i<n;++i) a[i].x/=n;
45 }
46 int main(){
47     while (scanf("%c",&s)&&isalpha(s))
48         s=='a'?c[++++n]=1:c[++++n]=2;
49     c[0]=-1; c[n+2]=-2;
50     for (int i=1;i<=n;++i){
51         if (x+f[x]>i) f[i]=min(f[x+x-i],x+f[x]-i);
52         while (c[i+f[i]]==c[i-f[i]]) ++f[i]; --f[i];
53         if (i+f[i]>x+f[x]) x=i;
54         ans+=f[i]/2; if (ans>=mo) ans-=mo;
55     }
56     m=ceil((log(n)/log(2))); m=1<<m;
57     for (int i=1;i<m;++i)rev[i]=(rev[i>>1]>>1)+(m>>1)*(i&1);
58     x=0; for (int i=2;i<=n;++++i) c[++x]=c[i]; n=x;
59     for (int i=1;i<=n;++i) c[i]==1?a[i].x=1:b[i].x=1;
60     fft(a,m);  fft(b,m);
61     for (int i=0;i<m;++i) a[i]=a[i]*a[i],b[i]=b[i]*b[i];
62     fft(a,m,-1); fft(b,m,-1);
63     h[0]=1; for (int i=1;i<=n;++i)h[i]=(h[i-1]+h[i-1])%mo;
64     int x;  ans=mo-ans; 
65     for (int i=1;i<n+n;++i){
66         x=round(a[i].x+b[i].x); 
67         ans+=h[x+1>>1]-1; if (ans>=mo) ans-=mo;
68     }
69     ans=(ans-n+1+mo)%mo;
70     printf("%lld",ans);
71     return 0;
72 }
KriTo

  

然后 顺手写了个ntt板子扔这(没用题目测过对不对)

mo的原根g的定义:g^1,g^2,...,g^(mo-1) 在%mo意义下各不相同。

 1 #include <bits/stdc++.h>
 2 #define LL long long
 3 using namespace std;
 4 int g1,g2,N,n,k,x,W[1050000],a[1050000],b[1050000],rev[1050000],mo1,mo2;
 5 LL po(LL x,LL y,LL mo){
 6     LL z=1; if (y<0) y=y%(mo-1)+mo-1;
 7     for (;y;y>>=1,x=x*x%mo)
 8     if (y&1) z=z*x%mo;
 9     return z;
10 }
11 int getg(LL mo){
12     LL y=mo-1,x=floor(sqrt(y)); int fl; 
13     for (int g=2;;++g){
14         fl=1;
15         for (int i=2;i<=x;++i) if (!(y%i))
16         if (po(g,i,mo)==1||po(g,y/i,mo)==1) {fl=0;break;}
17         if (fl) return g;
18     }
19 }
20 void ntt(int a[],int n,int d,int mo,int G){    //n整除(mo-1)
21     if (d<0) reverse(a+1,a+n);
22     for (int i=0;i<n;++i)
23         if (i<rev[i]) swap(a[i],a[rev[i]]);
24     W[0]=1; LL X=po(G,(mo-1)/n,mo);
25     for (int i=1;i<n/2;++i) W[i]=X*W[i-1]%mo;
26     for (int m=2,k=1;m<=n;k=m,m<<=1)
27         for (int i=0;i<n;i+=m)
28         for (int j=i;j<i+k;++j){
29             int u=a[j],v=1ll*a[j+k]*W[n/m*(j-i)]%mo;
30             a[j]=u+v>=mo?u+v-mo:u+v;
31             a[j+k]=u-v<0?u-v+mo:u-v;
32         }
33     if (d<0){
34         X=po(n,mo-2,mo);
35         for (int i=0;i<n;++i) a[i]=X*a[i]%mo;
36     }
37 }
38 int main(){
39     mo1=998244353; mo2=1004535809;
40     g1=getg(mo1); g2=getg(mo2);
41     scanf("%d%d",&n,&k); W[0]=1;
42     for (int i=1;i<=n;++i)
43         scanf("%d",&x),a[x]=1,b[x]=1;
44     N=1048576;
45     for (int i=0;i<N;++i) rev[i]=rev[i>>1]>>1|(i&1?N>>1:0);
46     ntt(a,N,1,mo1,g1); ntt(b,N,1,mo2,g2);
47     for (int i=0;i<N;++i)
48         a[i]=po(a[i],k,mo1),b[i]=po(b[i],k,mo2);
49     ntt(a,N,-1,mo1,g1); ntt(b,N,-1,mo2,g2);
50     for (int i=0;i<N;++i){
51         if (a[i]<0) a[i]+=mo1;
52         if (b[i]<0) b[i]+=mo2;
53     }
54     for (int i=0;i<N;++i) if (a[i]||b[i]) printf("%d ",i); puts("");
55     return 0;
56 }
AsuNa

 

若多项式相乘的最高次为n, 则FFT,NTT的数组大小要开到>n的最小的2的幂。 即 1<<(int)ceil(log(n+1)/log(2))

给几个模数:

1004535809=479*2^21+1,   原根=3

998244353=7*17*2^23+1 ,原根=3

469762049=7*2^26+1      ,原根=3

转载于:https://www.cnblogs.com/cyz666/p/6382844.html

这篇关于BZOJ3160【万径人踪灭】 【FFT】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/385422

相关文章

【数字信号处理】一文讲清FFT(快速傅里叶变换)

目录 快速傅里叶变换(Fast Fourier Transform,FFT)FFT的背景快速傅里叶变换(Fast Fourier Transform,FFT)DFT的数学表达实际计算重要性和应用频谱泄露、频谱混叠奈奎斯特采样定理参考链接 快速傅里叶变换(Fast Fourier Transform,FFT) FFT的背景 1、为什么要时域→频域频率?50Hz+频率120Hz

【BNU】40719 Arithmetic Progressions【分块+FFT】

传送门:【BNU】40719 Arithmetic Progressions 题目分析: 用分块+FFT强行AC了这题…… 之前一直TLE……然后改了好久把姿势改的优美点了……终于过了…… 大概思路是:我们考虑分块,假设每一块的大小为S,一共分了B块然后我们分两种情况讨论: 1.第二个数在第i块,第一个数在(1~i-1)块内,第三个数在(i+1~B)块内。 2.至少两个数在同一块内。

【HDU】5197 DZY Loves Orzing 【FFT启发式合并】

传送门:【HDU】5197 DZY Loves Orzing 题目分析: 首先申明,我不会 dp dp方程= =……这个东西给队友找出来了,然后我就是套这个方程做题的Qrz…… 对于这题,因为 n2 n^2个数互不相同,所以每一列都可以单独考虑。设 dpni dp_ni表示长度为 n n的排列,能恰好看见ii个人的方案数,根据队友的发现, dpni dp_ni就等于 |sni| |s_ni|

【ZOJ】3874 Permutation Graph 【FFT+CDQ分治】

传送门:【ZOJ】3874 Permutation Graph 题目分析: 容易知道一个个连通块内部的标号都是连续的,否则一定会有另一个连通块向这个连通块建边,或者这个连通块向另一个连通块建边。而且从左到右左边的连通块内最大的标号小于右边连通块内最小的标号。 然后我们可以构造dp方程: dp[n]=n!−i!∗dp[n−i] \qquad \qquad dp[n] = n! - i! *

【SPOJ】Triple Sums【FFT】

传送门:【SPOJ】Triple Sums 题目分析: 首先我们不考虑 i<j<k i<j<k这个条件,构造多项式: Y=∑xai \qquad\qquad\qquad Y = \sum x^{a_i} 那么 ai+aj+ak=S ai+aj+ak=S的个数即 xai+aj+ak=S x^{a_i+a_j+a_k=S}的个数,等价于 Y3中xS Y^3中x^S的系数。 然后我们考虑容斥

【BNU】33943 Super Rooks on Chessboard 【FFT】

【BNU】33943 Super Rooks on Chessboard UVA上的题,然而我怎么会蠢到去UVA呢!(其实是百度首先跳出来的是BNU → \to_ → \to) 题目分析: 设 numx numx为 N N个车没有覆盖的行数,numynumy为 N N个车没有覆盖的列数。 首先我们考虑没有主对角线覆盖这一条件时,总共的没有被覆盖的面积就是numx∗numynumx \ast

【HDU】4609 3-idiots 【FFT】

传送门:【HDU】4609 3-idiots 题目分析: 我们考虑两边长度之和为 n n的方案数,设num[x]num[x]为长度为 x x的个数,那么∑nx=1num[n−x]∗num[x]\sum_{x=1}^{n}{num[n-x]*num[x]} 即两边长度之和为 n n的方案数。容易发现这这正是卷积!然后我们就可以愉快的用FFTFFT预处理出所有的两边长度之和为i的方案数。 FFT

【codechef】 Prime Distance On Tree【求树上路经长度为i的路径条数】【点分治+FFT】

传送门:【codechef】 Prime Distance On Tree 点分治+FFT水题……竟然n*n爆int没发现…… 而且NTT TLE,FFT跑的超级快…… my  code: my~~code: #include <bits/stdc++.h>using namespace std ;typedef long long LL ;#define clr( a , x ) m

【51nod】算法马拉松4 F 移数字 【快速求N!%P】【FFT】

传送门:【51nod】算法马拉松4 F 移数字 涉及知识点:多项式求逆,多项式除法,多点插值,阶乘取模。 对于N!%P,复杂度为 O(N−−√log2N−−√) O(\sqrt N \log^2\sqrt N)。 但常数巨大,和暴力算实际复杂度只相差常数= = 这个是可以扩展到组合数取模的~ my  code: my~~code: #include <stdio.h>#includ

【HDU】5958 New Signal Decomposition【离散对数下的FFT】

题目链接:【HDU】5958 New Signal Decomposition 在此先感谢小q对我的指导,没有q老师的帮助,估计永远也做不出来了。 首先我们考虑对这个式子做离散对数。令 g g为pp的某个原根,则有: bi=∑p−1j=0aj⋅r(i,j) \quad b_i=\sum_{j=0}^{p-1}a_j\cdot r(i,j) bi=∑p−1j=0aj⋅2sin32πi⋅j