2015-2016 ACM-ICPC, Central Europe Regional Contest (CERC 15) F.Frightful Formula(大数NTT)

题目链接:http://codeforces.com/gym/101480/attachments


mark一下O(1)快速乘,啥原理啊?还有这个长度计算,貌似也得好好学学啊?


代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD=1e6+3;
const int MAXN=1<<21;//玄学:开成两倍会有问题(1<<17=131072,1<<18=262144)
const int M=2e5+5;
ll qpow(ll a,ll b)
{
	ll ret=1;
	a%=MOD;
	while(b)
	{
		if(b&1)
		{
			ret=ret*a%MOD;
		}
		a=(a*a)%MOD;
		b>>=1;
	}
	return ret%MOD;
}
namespace NTT
{
    typedef long long ll;
    const ll MOD=1945555039024054273LL;
    const ll g=5;
	ll mul(ll x,ll y)
	{
    	return (x*y-(ll)(x/(long double)MOD*y+1e-6)*MOD+MOD)%MOD;
	}
    ll qpow(ll a,ll k)
    {
        ll res=1LL;
        while(k>0)
        {
            if(k&1)res=mul(res,a);
            a=mul(a,a);
            k>>=1;
        }
        return res;
    }
    void change(ll y[],int len)
    {
        for(int i=1,j=len/2;i<len-1;i++)
        {
            if(i<j)swap(y[i],y[j]);
            int k=len/2;
            while(j>=k)
            {
                j-=k;
                k/=2;
            }
            if(j<k)j+=k;
        }
    }
    void ntt(ll y[],int len,int on)
    {
        change(y,len);
        for(int h=2;h<=len;h<<=1)
        {
            ll wn=qpow(g,(MOD-1)/h);
            if(on==-1)wn=qpow(wn,MOD-2);
            for(int j=0;j<len;j+=h)
            {
                ll w=1LL;
                for(int k=j;k<j+h/2;k++)
                {
                    ll u=y[k];
                    ll t=mul(w,y[k+h/2]);
                    y[k]=(u+t)%MOD;
                    y[k+h/2]=(u-t+MOD)%MOD;
                    w=mul(w,wn);
                }
            }
        }
        if(on==-1)
        {
            ll t=qpow(len,MOD-2);
            for(int i=0;i<len;i++)
                y[i]=mul(y[i],t);
        }
    }
    void cal(ll x1[],ll x2[],ll tot)
    {
        int len=1;
        while(len<2*tot)len<<=1;  
        ntt(x1,len,1);
        ntt(x2,len,1);
        for(int i=0;i<len;i++)
            x1[i]=mul(x1[i],x2[i]);
        ntt(x1,len,-1);
    }
}

ll A[M],B[M];
ll fact[M*2],inv[M*2];
ll F1[MAXN],F2[MAXN],res[MAXN];
void init()
{
	fact[0]=1;
	inv[0]=1;
	for(int i=1;i<M*2;i++)
		fact[i]=fact[i-1]*i%MOD;
	for(int i=1;i<M*2;i++)
		inv[i]=qpow(fact[i],MOD-2);
}
ll C(ll n,ll m)
{
	return fact[n]*inv[m]%MOD*inv[n-m]%MOD;
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	init();
	int n;
	ll a,b,c;
	ll ans=0;
	scanf("%d%lld%lld%lld",&n,&a,&b,&c);
	for(int i=1;i<=n;i++)
		scanf("%lld",&A[i]);
	for(int i=1;i<=n;i++)
		scanf("%lld",&B[i]);
	for(int i=2;i<=n;i++)
	{
		ans=(ans+C(n-1+n-i-1,n-i)*qpow(b,n-1)%MOD*qpow(a,n-i)%MOD*B[i]%MOD)%MOD;
		ans=(ans+C(n-1+n-i-1,n-i)*qpow(b,n-i)%MOD*qpow(a,n-1)%MOD*A[i]%MOD)%MOD;
	}
	for(int i=2;i<=n;i++)
	{
		F1[i]=qpow(b,n-i)*inv[n-i]%MOD;
		F2[i]=qpow(a,n-i)*inv[n-i]%MOD;
	}
	NTT :: cal(F1,F2,n+1);
	for(int i=0;i<=2*n;i++)
	{
		F1[i]%=MOD;
		ans=(ans+fact[2*n-i]*F1[i]%MOD*c%MOD)%MOD;
	}
	printf("%lld\n",ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值