【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)

4332: JSOI2012 分零食

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 119  Solved: 66

Description

这里是欢乐的进香河,这里是欢乐的幼儿园。

今天是2月14日,星期二。在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着。校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们。听到这个消息,所有同学都安安静静地排好了队,大家都知道,校长不喜欢调皮的孩子。

同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U。如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是f(x)=O*x2+S*x+U。

现在校长开始分糖果了,一共有M个糖果。有些小朋友可能得不到糖果,对于那些得不到糖果的小朋友来说,欢乐程度就是1。如果一位小朋友得不到糖果,那么在她身后的小朋友们也都得不到糖果。(即这一列得不到糖果的小朋友一定是最后的连续若干位)

所有分糖果的方案都是等概率的。现在问题是:期望情况下,所有小朋友的欢乐程度的乘积是多少?呆呆同学很快就有了一个思路,只要知道总的方案个数T和所有方案下欢乐程度乘积的总和S,就可以得到答案Ans=S/T。现在他已经求出来了T的答案,但是S怎么求呢?他就不知道了。你能告诉他么?

因为答案很大,你只需要告诉他S对P取模后的结果。

后记:

虽然大家都知道,即便知道了T,知道了S对P取模后的结果,也没有办法知道期望情况下,所有小朋友欢乐程度的乘积。但是,当呆呆想到这一点的时候,已经彻底绝望了。

Input

第一行有2个整数,分别是M和P。

第二行有一个整数A,第三行有一个整数O。

第四行有一个整数S,第五行有一个整数U。

Output

一个整数S,因为答案可能很大,你只需要输出S 对P取模后的结果。

Sample Input

4 100

4

1

0

0

Sample Output

63

样例说明

函数f(x)=x^2。一共有4份零食,4位同学。如果只有第一个同学得到,欢乐程度为16,若前两位同学得到,欢乐程度的所有可能依次为9,9,16,若有三位同学得到,欢乐程度有4,4,4,最后一种情况,每一个同学都得到了零食,欢乐程度为1。相加后得到S=63。

应上传者要求,此题不公开,如有异议,请提出.

HINT

对于100%的数据,M<=10000,P<=255,A<=108,O<=4,S<=300,U<=100。

Source

【分析】

  从7点搞到了现在。。

  理解奥爷爷的代码好久啊。。。但是打的真心短。。。

  下面那个qpow是一个矩阵乘法的快速幂!!【我傻啊看了很久才看出来。。

  所以求$G^1+G^2+...G^n$

呵呵【我看这个看了好久

【呵呵

其实我觉得这个卷积有点迷

但是不管了,明天再说

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 #define Maxn 10010*4
 9 const double pi=acos(-1);
10 int Mod;
11
12 struct P
13 {
14     double x,y;
15     P() {x=y=0;}
16     P(double x,double y):x(x),y(y){}
17     friend P operator + (P x,P y) {return P(x.x+y.x,x.y+y.y);}
18     friend P operator - (P x,P y) {return P(x.x-y.x,x.y-y.y);}
19     friend P operator * (P x,P y) {return P(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);}
20 }a[Maxn],b[Maxn];
21
22 int R[Maxn],nn,m;
23 void dft(P *a,int f)
24 {
25     for(int i=0;i<nn;i++) if(i<R[i]) swap(a[i],a[R[i]]);
26     for(int i=1;i<nn;i<<=1)
27     {
28         P wn(cos(pi/i),f*sin(pi/i));
29         for(int j=0;j<nn;j+=i<<1)
30         {
31             P w(1,0);
32             for(int k=0;k<i;k++,w=w*wn)
33             {
34                 P x=a[j+k],y=w*a[j+k+i];
35                 a[j+k]=x+y;a[j+k+i]=x-y;
36             }
37         }
38     }
39     if(f==-1)
40     {
41         for(int i=0;i<=nn;i++) a[i].x/=nn,a[i].y/=nn;
42     }
43 }
44
45 int A[Maxn],B[Maxn],C[Maxn],nw[Maxn];
46 int aa,bb,cc;
47 void fft(int *A,int *B)
48 {
49     for(int i=0;i<nn;i++)
50     {
51       a[i].x=A[i];a[i].y=0;
52       b[i].x=B[i];b[i].y=0;
53     }
54     dft(a,1);dft(b,1);
55     for(int i=0;i<=nn;i++) a[i]=a[i]*b[i];
56     dft(a,-1);
57     for(int i=1;i<=m;i++) A[i]=((int)(a[i].x+0.5)%Mod);
58 }
59
60 void add(int *A,int *B)
61 {
62     for(int i=1;i<=m;i++) A[i]=(A[i]+B[i])%Mod;
63 }
64
65 void qpow(int k)
66 {
67     for(int i=0;i<=m;i++) A[i]=0;
68     for(int i=1;i<=m;i++) C[i]=B[i]=(aa*i*i+bb*i+cc)%Mod;
69     while(k)
70     {
71         if(k&1)
72         {
73             fft(A,B);
74             add(A,C);
75         }
76         for(int i=1;i<=m;i++) nw[i]=C[i];
77         fft(C,B);
78         add(C,nw);
79         fft(B,B);
80         k>>=1;
81     }
82 }
83
84 int main()
85 {
86     int n;
87     scanf("%d%d%d%d%d%d",&m,&Mod,&n,&aa,&bb,&cc);
88     if(n>m) n=m;
89     nn=1;int ll=0;
90     while(nn<=2*m) nn<<=1,ll++;
91     for(int i=0;i<=nn;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(ll-1));
92     qpow(n);
93     printf("%d\n",A[m]);
94     return 0;
95 }

2017-04-14 21:46:24

时间: 2024-10-20 09:41:00

【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)的相关文章

【codeforces 623E】dp+FFT+快速幂

题目大意:用$[1,2^k-1]$之间的证书构造一个长度为$n$的序列$a_i$,令$b_i=a_1\ or\ a_2\ or\ ...\ or a_i$,问使得b序列严格递增的方案数,答案对$10^9+7$取模. 数据范围,$n≤1^{18}$,$k≤30000$. 考虑用dp来解决这一题,我们用$f[i][j]$来表示前$i$个数中,使用了$j$个二进制位(注意!并不是前$j$个),那么答案显然为$\sum_{i=0}^{k} \binom{n}{i} \times f[n][i]$. 考虑

P3321 [SDOI2015]序列统计 FFT+快速幂+原根

\(\color{#0066ff}{ 题目描述 }\) 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题需要你的帮助:给定整数x,求所有可以生成出的,且满足数列中所有数的乘积mod M的值等于x的不同的数列的有多少个.小C认为,两个数列{Ai}和{Bi}不同,当且仅当至少存在一个整数i,满足Ai≠Bi.另外,小C认为这个问题的答案可能很大,因此他只需要你

luogu_P2054 bzoj 1965 洗牌 【题解】 快速幂 快速乘

题目链接: Luogu:https://www.luogu.org/problem/P2054 bzoj:https://www.lydsy.com/JudgeOnline/problem.php?id=1965 找到规律: 上一次在x位置,下一次就会在 x*2%(n+1) 位置 那么就是要求: x * (2^m) = L(mod n+1) 第一反应exgcd,但是突然感觉有点不太优秀. 因为n是偶数(题目说了) 所以2和n+1为互质 所以设 z *  2 =1(mod n+1) z就为2在mo

[BZOJ 2875][NOI 2012]随机数生成器(矩阵快速幂)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2875 题目居然没给描述,我特么真无语了...好吧我来发个题目描述: 给出a,c,g,mod,x0,n,xn=(a*xn-1+c)%mod,求xn%g 联想用矩阵快速幂在logn的复杂度下求斐波那契数列,对这题我们也可以采取类似的方法. 我们用矩阵运算来改装这个递推式: 设 那么 于是可以直接用矩阵快速幂求A矩阵的n次方,然后再乘上x0即可得出xn 此题还有两个坑点: 1.xn求出

[BZOJ 1297][SCOI 2009]迷路(矩阵快速幂)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1297 分析:如果每条边的边权都是1,那么就相当于对邻接矩阵自乘T次(因为写一下递推式子f[i][j]=∑f[i][k]*f[k][j]等价于矩阵乘法的定义).但是这题每条边的边权是1~9. 所以可以把每个点i拆成9个点形成链状:i9->i8->i7->i6->i5->i4->i3->i2->i1 (这条链中每条边的长度都为1) 然后对于原图中的

[BZOJ 2326][HNOI 2011]数学作业(矩阵快速幂)

蒟蒻线性代数太烂了...这个逼题居然卡了半天才做出来,弱的不行啊... 矩阵快速幂,把n这个len位数拆成len次分段快速幂就可以了. 注意取模的数字m<=1e9,所以矩阵乘法运算时要先对乘数取模,防止中间运算结果太大溢出,坑爹啊 代码: #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #d

BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )

写了一个早上...就因为把长度为m的也算进去了... dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j)表示dp(x-1, j)对dp(x, i)的贡献.然后用矩阵快速幂就可以了. 时间复杂度O(M3logN + M) ------------------------------------------------------------------- #include<bits/stdc++.h>

bzoj千题计划309:bzoj4332: JSOI2012 分零食(分治FFT)

https://www.lydsy.com/JudgeOnline/problem.php?id=4332 因为如果一位小朋友得不到糖果,那么在她身后的小朋友们也都得不到糖果. 所以设g[i][j] 表示前i位小朋友,分到j个糖果,且前i位小朋友都分到糖果的方案数 令F(x) 表示分到x个糖果的欢乐程度 ∴g[i][j] = ∑ g[i-1][j-k]*F(k) 记g[i]=g[i-1]*F,则 g[i]=F ^ i 但是要求的是 Σ g[i][m] 记f[n]=Σ g[i]  i∈[1,n]

BZOJ 4332 FFT+快速幂

思路: 最裸的方程:f[i][j]=Σf[i-1][j-k]*F[k] 诶呦 这不是卷积嘛 f[i]就可以用f[i-1]卷F 求到 但是这样还是很慢 设p[i] 为Σ f[j](1<=j<=i) 发现p可以倍增推 于是  就 倍增一下  就完了... http://www.cnblogs.com/Skyminer/p/6561689.html hz神犇的题解写得非常详细.. //By SiriusRen #include <cmath> #include <cstdio>