多项式
Description
Input
输入文件共三行,第一行为一个正整数n,第二行为一个非负整数t,第三行为一个非负整数m。
Output
输出一行,为N的值。
Sample Input
3
2
2
Sample Output
10536
HINT
对于100%的数据,0 < n ≤ 103000,0 ≤ t ≤ 10000,0 ≤ n-m ≤ 5
做完这题以后满脑子想的都是都是”放飞出题人”……
这™明明是一道数学题技术含量都在高精度上是什么鬼……
(╯‵□′)╯︵┻━┻
思路:
考虑变形:
∑nk=0ak(x+t)k=∑nk=0bkxk
暴力展开左边:
∑nk=0ak∑ki=0(ik)xitk−i=∑nk=0bkxk
发现
x
的取值不确定,那么显然对于每个
那么将x提前,考虑每个其余部分对每个
xi
的贡献:
∑ni=0xi∑nk=i(ik)aktk−i=∑ni=0bixi
可以发现:
bi=∑nk=i(ik)aktk−i
令下标为m,同时变一下形:
bm=∑n−mk=0(kk+m)am+ktk
发现
n−m<=5
,已经可以接受暴力计算了~
这里的组合数根据定义暴力展开会发现上下可以通分成一个相对很小的分数。
至于a,暴力展开可以发现这是一个等比数列求和加上一个数的幂,等比数列直接上求和公式,数的幂则可以考虑用费马小定理给次数模上模数-1以避免幂次爆long long。
然后就是无比蛋疼的高精度了……
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int md=3389;
namespace chutirenbudehaosi
{
const int N=2009;
const ll base=(ll)1000000000;
const ll pows[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
struct bigint
{
ll a[N],len;
ll &operator [] (int x){return a[x];}
inline void init(ll x)
{
len=1;
a[1]=x;
while(a[len]>=base)
{
len++;
a[len]=a[len-1]/base;
a[len-1]%=base;
}
}
bigint(ll x=0){memset(a,0,sizeof(a));init(x);}
inline void operator = (ll x){init(x);}
inline void flush(){while(len>=1 && !a[len])--len;}
inline bigint operator + (bigint b)
{
bigint ret;
ret.len=max(len,b.len);
for(int i=1;i<=ret.len;i++)
{
ret[i]+=a[i]+b[i];
if(ret[i]>=base)
{
ret[i+1]+=ret[i]/base;
ret[i]%=base;
}
}
if(ret[len+1])
len++;
return ret;
}
inline bigint operator + (ll b)
{
bigint ret;
ret=(*this);
ret[1]+=b;
int pos=1;
while(ret[pos]>=base)
{
ret[pos+1]+=ret[pos]/base;
ret[pos++]%=base;
}
return ret;
}
friend bigint operator - (bigint a,bigint b)
{
bigint ret;
ret.len=max(a.len,b.len);
ll tmp=0;
for(int i=1;i<=ret.len;i++)
{
ret[i]=tmp+a[i]-b[i];
tmp=0;
if(ret[i]<0)
{
ret[i]+=((-ret[i]-1)/base+1)*base;
tmp-=base;
}
}
ret.flush();
return ret;
}
inline bigint operator * (bigint b)
{
bigint ret;
ret.len=len+b.len;
for(int i=1;i<=len;i++)
{
ll tmp=0;
for(int j=1;j<=b.len+1;j++)
{
tmp+=a[i]*b[j]+ret[i+j-1];
ret[i+j-1]=tmp%base;
tmp/=base;
}
}
ret.flush();
return ret;
}
inline bigint operator * (ll b)
{
bigint x(b);
return (*this)*x;
}
inline bigint operator / (ll b)
{
bigint ret;
ret.len=len;
ll tmp=0;
for(int i=len;i>=1;i--)
{
tmp=tmp*base+a[i];
ret[i]=tmp/b;
tmp%=b;
}
ret.flush();
return ret;
}
inline ll operator % (ll b)
{
ll ret=0;
for(int i=len;i>=1;i--)
ret=(ret*base+a[i])%b;
return ret;
}
};
inline void write(bigint a)
{
printf("%lld",a[a.len]);
for(int i=a.len-1;i>=1;i--)
printf("%09d",a[i]);
putchar('\n');
}
char s[20000009];
inline bigint read()
{
scanf("%s",s+1);
bigint x(0);
int len=strlen(s+1);
for(int i=len;i>=1;i--)
x[(len-i)/9+1]+=(s[i]^48)*pows[(len-i)%9];
x.len=len/9+2;
return x;
}
}
using namespace chutirenbudehaosi;
inline ll reads()
{
ll x=0;char ch=getchar();
while(ch<'0' || '9'<ch)ch=getchar();
while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();
return x;
}
inline ll qpow(ll a,ll b)
{
ll ret=1;
while(b)
{
if(b&1)
ret=ret*a%md;
a=a*a%md;
b>>=1;
}
return ret;
}
inline int a(bigint x)
{
return (209*qpow(1234,x%(md-1))+3181)%md;
}
bigint n,m,c(1),tt(1),ans;
ll t;
int main()
{
n=read();
t=reads();
m=read();
ll delta=(n-m)%base;
for(int i=0;i<=delta;i++)
{
if(i)
{
c=c*(m+i);
c=c/i;
tt=tt*t;
}
ans=ans+c*tt*a(m+i);
}
write(ans);
return 0;
}