51nod 1258 序列求和 V4

跪烂(貌似我记得,是我要学习多项式的一些东西,然后发现可以搞伯努利数,然后就奇怪的入坑了)

这个题显然是不可以n^2来预处理伯努利数的

那怎么办呢。。。。。。。。找题解啊。。。

这里有伯努利数的生成函数,(不知道怎么推的),然后搞一搞就成了一个多项式求逆的样子。

而且这个题还有一个BT的就是,1e9+7是不能写成1+2^k*n的形式的,所以就没有办法直接NTT,这里还要用到一个三模数NTT,就是取出3个满足1+2^k*n形式的大质数(先假设为a,b,c吧),满足a*b*c>n*P*P(P在这里就是1e9+7)(虽然不知道为什么)

然后三模数NTT最后当然是要用CRT来合并的,这里直接CRT合并的话long long就炸掉了,所以用一点小技巧http://blog.csdn.net/u014609452/article/details/68058602

大概就好了吧。呵呵。。

  1 #include<bits/stdc++.h>
  2 #define LL long long
  3 using namespace std;
  4
  5 const int mod=1e9+7;
  6 const int M[]={998244353,1004535809,469762049};
  7 const int G[]={3,3,3};
  8 const LL _M=(LL)M[0]*M[1];
  9
 10 LL ksm(LL a, int b, int p)
 11 {
 12     LL sum=1; a%=p;
 13     for (;b;b>>=1,a=a*a%p)
 14         if (b&1) sum=sum*a%p;
 15     return sum;
 16 }
 17 LL mul(LL a, LL b, LL p)
 18 {
 19     a%=p; b%=p;
 20     return ((a*b-(LL)((LL)((long double)a/p*b+1e-3)*p))%p+p)%p;
 21 }
 22
 23 const int m1=M[0],m2=M[1],m3=M[2];
 24 const int inv1=ksm(m1%m2,m2-2,m2),inv2=ksm(m2%m1,m1-2,m1),inv12=ksm(_M%m3,m3-2,m3);
 25 int CRT(int a1, int a2, int a3)
 26 {
 27     LL A=(mul((LL)a1*m2%_M,inv2,_M)+mul((LL)a2*m1%_M,inv1,_M))%_M;
 28     LL k=((LL)a3+m3-A%m3)*inv12%m3;
 29     return (k*(_M%mod)+A)%mod;
 30 }
 31
 32 const int N=264000;
 33 int R[N];
 34 struct NTT{
 35     int P,G;
 36     int num,w[2][N];
 37     void pre(int _P, int _G, int m)
 38     {
 39         num=m; P=_P; G=_G;
 40         int g=ksm(G,(P-1)/num,P);
 41         w[1][0]=1; for (int i=1; i<num; i++) w[1][i]=(LL)w[1][i-1]*g%P;
 42         w[0][0]=1; for (int i=1; i<num; i++) w[0][i]=w[1][num-i];
 43     }
 44     void FFT(int *a, int n, int f)
 45     {
 46         for (int i=0; i<n; i++) if (i<R[i]) swap(a[i],a[R[i]]);
 47         for (int i=1; i<n; i<<=1)
 48             for (int j=0; j<n; j+=(i<<1))
 49                 for (int k=0; k<i; k++)
 50                 {
 51                     int x=a[j+k],y=(LL)a[j+k+i]*w[f][num/(i<<1)*k]%P;
 52                     a[j+k]=(x+y)%P; a[j+k+i]=(x-y+P)%P;
 53                 }
 54         if (!f) for (int i=0,inv=ksm(n,P-2,P); i<n; i++) a[i]=(LL)a[i]*inv%P;
 55     }
 56 }ntt[3];
 57
 58 int tmp[N],b2[N],b3[N],_b[3][N],c[N];
 59
 60 void get_inv(int *a, int *b, int n)
 61 {
 62     if (n==1) return void(b[0]=CRT(ksm(a[0],m1-2,m1),ksm(a[0],m2-2,m2),ksm(a[0],m3-2,m3)));
 63     get_inv(a,b,n>>1);
 64     int L=0; while (!(n>>L&1)) L++;
 65     for (int i=1; i<(n<<1); i++) R[i]=(R[i>>1]>>1)|((i&1)<<L);
 66
 67     for (int i=0; i<n; i++) b2[i]=b3[i]=b[i],tmp[i]=a[i],b2[i+n]=b3[i+n]=0;
 68     ntt[0].FFT(b,n<<1,1); ntt[1].FFT(b2,n<<1,1); ntt[2].FFT(b3,n<<1,1);
 69
 70     for (int I=0; I<3; I++)
 71     {
 72         int *d=I==0?b:(I==1?b2:b3);
 73         for (int i=0; i<n; i++) tmp[i+n]=0,tmp[i]=a[i];
 74         ntt[I].FFT(tmp,n<<1,1);
 75         for (int i=0; i<(n<<1); i++) tmp[i]=(LL)tmp[i]*d[i]%M[I];
 76         ntt[I].FFT(tmp,n<<1,0);
 77         for (int i=0; i<(n<<1); i++) _b[I][i]=tmp[i];
 78     }
 79
 80     for (int i=0; i<(n<<1); i++) c[i]=CRT(_b[0][i],_b[1][i],_b[2][i]),c[i]=c[i]==0?0:mod-c[i];
 81     c[0]=(c[0]+2)%mod;
 82
 83     for (int I=0; I<3; I++)
 84     {
 85         int *d=I==0?b:(I==1?b2:b3);
 86         for (int i=0; i<n; i++) tmp[n+i]=0,tmp[i]=c[i];
 87         ntt[I].FFT(tmp,n<<1,1);
 88         for (int i=0; i<(n<<1); i++) tmp[i]=(LL)tmp[i]*d[i]%M[I];
 89         ntt[I].FFT(tmp,n<<1,0);
 90         for (int i=0; i<(n<<1); i++) _b[I][i]=tmp[i];
 91     }
 92
 93     for (int i=0; i<n; i++) b[i]=CRT(_b[0][i],_b[1][i],_b[2][i]),b[n+i]=0;
 94 }
 95
 96 LL fac[N],inv[N];
 97
 98 void init(int n)
 99 {
100     fac[0]=inv[0]=inv[1]=1;
101     for (int i=1; i<=n; i++) fac[i]=fac[i-1]*i%mod;
102     for (int i=2; i<=n; i++) inv[i]=(LL)(mod-mod/i)*inv[mod%i]%mod;
103     for (int i=2; i<=n; i++) inv[i]=inv[i-1]*inv[i]%mod;
104 }
105 LL C(int n, int m) {return fac[n]*inv[m]%mod*inv[n-m]%mod;}
106
107
108 int n,m;
109 int a[N],b[N];
110 int _a[3][N],B[N];
111
112 int solve(int n, int m)
113 {
114     static LL pw[N];
115 /*    pw[0]=1; for (int i=1; i<=m+1; i++) pw[i]=pw[i-1]*(n%mod)%mod;
116     LL ret=((LL)m+1)*((mod+1)>>1)%mod*pw[m]%mod;
117     for (int k=0; k<=m; k+=2) ret=(ret+C(m+1,k)*B[k]%mod*pw[m+1-k]%mod)%mod;;*/
118     pw[0]=1; for (int i=1; i<=m+1; i++) pw[i]=pw[i-1]*n%mod;
119     LL ret=0;
120     for (int k=1; k<=m+1; k++) ret=(ret+(LL)B[m+1-k]*pw[k]%mod*C(m+1,k)%mod)%mod;
121     return ret%mod*ksm(m+1,mod-2,mod)%mod;
122 }
123 int main()
124 {
125     n=50000;
126     for (m=1; m<=n; m<<=1);
127     for (int i=0; i<3; i++) ntt[i].pre(M[i],G[i],m<<1);
128     init(m+1);
129     for (int i=0; i<m; i++) a[i]=inv[i+1];
130     get_inv(a,b,m);
131     for (int i=0; i<m; i++) B[i]=(LL)b[i]*fac[i]%mod;
132     int T,_K; LL _n; scanf("%d",&T);
133     while (T--)
134     {
135         scanf("%lld%d",&_n,&_K); _n++; _n%=mod;
136         printf("%d\n",solve(_n,_K));
137     }
138     return 0;
139 }
时间: 2024-08-10 11:54:43

51nod 1258 序列求和 V4的相关文章

51nod 1228 序列求和

伯努利数,刚! 自然数幂和神犇的blog:  http://blog.csdn.net/acdreamers/article/details/38929067 伯努利数的2个重要的式子: 为什么图片这么大... 这样的话n^2预处理出伯努利数,然后就可做了 1 #include <bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 5 const int M=2005; 6 const int maxn=2050; 7

51nod1258 序列求和V4

T(n) = n^k,S(n) = T(1) + T(2) + ...... T(n).给出n和k,求S(n). 例如k = 2,n = 5,S(n) = 1^2 + 2^2 + 3^2 + 4^2 + 5^2 = 55. 由于结果很大,输出S(n) Mod 1000000007的结果即可. Input 第1行:一个数T,表示后面用作输入测试的数的数量.(1 <= T <= 500) 第2 - T + 1行:每行2个数,N, K中间用空格分割.(1 <= N <= 10^18, 1

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

【蓝桥杯】 入门训练 序列求和

入门训练 序列求和 时间限制:1.0s   内存限制:256.0MB 问题描述 求1+2+3+...+n的值. 输入格式 输入包括一个整数n. 输出格式 输出一行,包括一个整数,表示1+2+3+...+n的值. 样例输入 4 样例输出 10 样例输入 100 说明:有一些试题会给出多组样例输入输出以帮助你更好的做题. 一般在提交之前所有这些样例都需要测试通过才行,但这不代表这几组样例数据都正确了你的程序就是完全正确的,潜在的错误可能仍然导致你的得分较低. 样例输出 5050 数据规模与约定 1

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

HDU 2254 奥运(矩阵快速幂+二分等比序列求和)

HDU 2254 奥运(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 2254 奥运 题意: 中问题不解释. 分析: 根据floyd的算法,矩阵的k次方表示这个矩阵走了k步. 所以k天后就算矩阵的k次方. 这样就变成:初始矩阵的^[t1,t2]这个区间内的v[v1][v2]的和. 所以就是二分等比序列求和上场的时候了. 跟HDU 1588 Gauss Fibonacci的算法一样. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * B

序列求和

入门训练 序列求和 时间限制:1.0s   内存限制:256.0MB 锦囊1 锦囊2 锦囊3 问题描述 求1+2+3+...+n的值. 输入格式 输入包括一个整数n. 输出格式 输出一行,包括一个整数,表示1+2+3+...+n的值. 样例输入 4 样例输出 10 样例输入 100 说明:有一些试题会给出多组样例输入输出以帮助你更好的做题. 一般在提交之前所有这些样例都需要测试通过才行,但这不代表这几组样例数据都正确了你的程序就是完全正确的,潜在的错误可能仍然导致你的得分较低. 样例输出 505

51_1228 序列求和(伯努利数)(转)

转自:http://blog.csdn.net/acdreamers/article/details/38929067 (ACdreamers) 分析:本题题意就是求自然数的幂和,但是它的case比较多.对于求幂和本身就需要的时间复杂度,如果继 续用上述方法来求自然数的幂和,5000个case会TLE,接下来介绍另一个求自然数幂和的方法,它是基于伯 努利数的,公式描述如下 可以看出只要我们预处理出每一项,就可以在线性时间内求得自然数的幂和.前面的倒数可以用递推法求逆元 预处理,组合数也可以预处理

蓝桥杯-入门训练 序列求和

入门训练 序列求和 时间限制:1.0s   内存限制:256.0MB 问题描述 求1+2+3+...+n的值. 输入格式 输入包括一个整数n. 输出格式 输出一行,包括一个整数,表示1+2+3+...+n的值. 样例输入 4 样例输出 10 样例输入 100 说明:有一些试题会给出多组样例输入输出以帮助你更好的做题. 一般在提交之前所有这些样例都需要测试通过才行,但这不代表这几组样例数据都正确了你的程序就是完全正确的,潜在的错误可能仍然导致你的得分较低. 样例输出 5050 数据规模与约定 1