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时

104060401
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;
}

 

posted @ 2017-10-15 21:38  GSHDYJZ  阅读(269)  评论(0编辑  收藏  举报