经测试,把所有数组空间都开大两倍可过。更为精确的结果是只要把第 10 行的 char s[500008]; 改为 char s[505008]; 就能通过了,而改成 char s[504008]; 却不行。这里的 s 数组是题目中输入的 n 的二进制表式,长度 ≤500000,但是 s 只在 43,44 行有出现。所以这是什么原因呢,有大佬愿意帮忙看看吗/kel/kel
#include<bits/stdc++.h>
#define LL long long
#define mod 1000000007
using namespace std;
int k,l,t=0;
LL n=0,ans=0,tmp,tmp1,tmp2;
int a[508],b[500008];
LL fac[508],inv[508],S[500008],pre[508],suf[508];
LL g[508][508],sum[508][508];
char s[500008];
inline LL Pow(LL a,int b)
{
if(!b)return 1;
if(b==1)return a;
LL c=Pow(a,(b>>1));
c=(c*c)%mod;
if(b&1)c=(c*a)%mod;
return c;
}
inline void init()
{
fac[0]=1;for(int i=1;i<=k+1;++i)fac[i]=(fac[i-1]*i)%mod;
inv[k+1]=Pow(fac[k+1],mod-2);for(int i=k+1;i;--i)inv[i-1]=(inv[i]*i)%mod;
}
inline LL C(int a,int b)
{
return (((fac[a]*inv[b])%mod)*inv[a-b])%mod;
}
inline LL calc(int x)
{
if(n-1<=k+1)return sum[n-1][x];
LL res=0,fz,fm;
for(int i=0;i<=k+1;++i)
{
fz=((i? pre[i-1]:1)*(i<=k? suf[i+1]:1))%mod;
fm=(((i-k-1)&1? -inv[k+1-i]:inv[k+1-i])*inv[i])%mod;
res=(res+((fz*fm)%mod)*sum[i][x])%mod;
}
return res;
}
int main()
{
scanf("%s%d",s,&k),l=strlen(s),init(),tmp=1;
for(int i=l-1;~i;--i,tmp=(tmp<<1)%mod)if(s[i]^48)b[++t]=l-1-i,S[t]=tmp,n=(n+tmp)%mod;
for(int i=t-1;i;--i)S[i]=(S[i]+S[i+1])%mod;
for(int i=0;i<=k+1;++i)pre[i]=((i? pre[i-1]:1)*(n-1-i))%mod,suf[k+1-i]=((i? suf[k+2-i]:1)*(n-1-(k+1-i)))%mod;
for(int i=0;i<k;++i)scanf("%d",&a[i]);
for(int i=0;i<=k+1;++i)
{
sum[i][0]=i+1;
for(int j=1;j<=k+1;++j)sum[i][j]=(sum[i-1][j]+Pow(i,j))%mod;
}
for(int i=0;i<k;++i)ans=(ans+calc(i)*a[i])%mod;
g[0][0]=tmp=1;
for(int i=0;i<k;++i,tmp=(tmp<<1)%mod)
for(int j=i+1;j<=k;++j)
{
g[i+1][j]=g[i][j],tmp1=1;
for(int o=j;~o;--o,tmp1=(tmp1*tmp)%mod)g[i+1][j]=(g[i+1][j]-((C(j,o)*tmp1)%mod)*g[i][o])%mod;
}
for(int i=0;i<k;++i)
{
tmp1=(t&1? a[i]:-a[i]);
for(int j=1;j<=t && b[j]<=k;++j,tmp1=-tmp1)
{
tmp=1,tmp2=0;
for(int o=i;~o;--o,tmp=(tmp*S[j+1])%mod)tmp2=(tmp2-((C(i,o)*tmp)%mod)*g[b[j]][o])%mod;
ans=(ans+tmp1*tmp2)%mod;
}
}
return 0&printf("%lld",(((ans*500000004)%mod)+mod)%mod);
}