Karen与测试 奇迹淫巧+快速幂
看到这题的复杂度就大概可以知道只是一道规律题了。
但问题是,规律是什么?
我们观察一下题目,不可能去模拟所有情况是吧,我们又发现所有想都是由上一层的数推过来的,于是我们可以把结果用最开始的给出项的系数直接算出来。
但问题又来了,n不同时,各项的系数怎么算呢?
于是我们开始找规律:
(下面的来自别人的博客)
n=4*k+1的时候,系数都是a1,0,a2,0,a3……a3,0,a2,0,a1的类型。
这是因为由一个固定的n=5的三角形(1,0,2,0,1)变化过来。
而且从加开始或从减开始都是一样的。
偶数位零是没用的,所以减法和加法也就是一样的(-0=+0)。
n=9时
1 | 0 | 4 | 0 | 6 | 0 | 4 | 0 | 1 |
---|---|---|---|---|---|---|---|---|
1 | 0 | 2 | 0 | 1 | ||||
1 | 0 | 2 | 0 | 1 | ||||
1 | 0 | 2 | 0 | 1 | ||||
1 | 0 | 2 | 0 | 1 |
把n暴力变成4*k+1的形式。O(4N)
而且这个系数除去0,跟杨辉三角的第2*(k/2)+1行是一模一样的。
杨辉三角:
1
11
121
1331
14641
……
快速幂……O(4N+N log mod)
代码(不是我的代码,我写的注释):
#include<cstdio> #include<cstring> #include<algorithm> #define imin(a,b) ((a<b)?(a):(b)) #define imax(a,b) ((a>b)?(a):(b)) using namespace std; typedef long long ll; const ll mods=1e9+7; const int N=200100; int n,col; int d[N]; ll f[2][N],ans;//f模拟最开始最多4次运算,因为只和上一行有关系,所以只保存两行 ll Pow(ll x,ll y) { ll s=1ll; for(;y;y>>=1) { if(y&1) s=(s*x)%mods; x=(x*x)%mods; } return s; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&d[i]),f[1][i]=d[i]; col=0; int o=1;//o是当前行,col是下一行 while((n%4)!=1)//把n转换到4×k+1上去 { o=o^1; for(int i=1;i<n;i++) { col^=1; if(col) f[o][i]=((f[o^1][i]+f[o^1][i+1])%mods+mods)%mods; else f[o][i]=((f[o^1][i]-f[o^1][i+1])%mods+mods)%mods; } n--; } ll yi=(n-1)>>1; ll C=1; for(int i=0;i<=yi;i++)//枚举这一行不为零的系数 { if(i) C=(C*(yi-i+1))%mods*Pow(i,mods-2)%mods;//系数 ans=(ans+C*f[o][i<<1|1]%mods)%mods; } printf("%lld\n",ans); return 0; }
PEACE