巨无语的一个题,卡时卡的~ 。除了各种优化外,还得开输入外挂才行,改了整整一天。 留个提醒自己。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int mod=998244353;
const int maxm=1e5+10;
const int maxn=2500;
long long num,p[maxm],pw[maxm],pm[maxm],dp[13][maxn];
int n,cnt,a[20],vis[maxn],cnt_c[maxn];
long long QuickMul(long long val,int n)
{
long long ans=1;
while(n)
{
if(n&1)
ans=ans*val%mod;
val=val*val%mod;
n>>=1;
}
return ans;
}
void Init()
{
memset(vis,-1,sizeof(vis));
for(int i=0;i<12;i++)
{
vis[1<<i]=i+1;
cnt_c[i+1]=2048/(1<<i);
}
p[0]=1;
for(int i=1;i<maxm;i++)
p[i]=p[i-1]*2%mod;
pw[0]=1,pm[0]=1;
for(int i=1;i<maxm;i++)
{
pw[i]=pw[i-1]*i%mod;
pm[i]=QuickMul(pw[i],mod-2);
}
}
inline long long C(int n,int m)
{
return pw[n]*pm[m]%mod*pm[n-m]%mod;
}
void Add(long long &a,long long b)
{
a=a+b;
if(a>=mod)
a-=mod;
}
void solve()
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=12;i++)
{
for(int j=0;j<=cnt_c[i-1];j++)
Add(dp[i][j>>1],dp[i-1][j]);
long long sum=1;
int num=min(a[i],cnt_c[i]);
for(int j=1;j<=num;j++)
{
long long val=C(a[i],j);
Add(sum,val);
for(int k=0;k<=cnt_c[i-1];k++)
if(dp[i-1][k])
Add(dp[i][min((k>>1)+j,cnt_c[i])],dp[i-1][k]*val%mod);
}
if(a[i]>cnt_c[i])
{
long long val=((p[a[i]]-sum)%mod+mod)%mod;
for(int k=0;k<=cnt_c[i-1];k++)
Add(dp[i][cnt_c[i]],dp[i-1][k]*val%mod);
}
}
printf("%I64d\n",dp[12][1]*p[cnt]%mod);
}
inline void read(int &x)
{
char ch;
while((ch=getchar())<'0'||ch>'9');
x=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
x=x*10+ch-'0';
}
int main()
{
Init();
int cas=1;
while(scanf("%d",&n)&&n)
{
cnt=0;
memset(a,0,sizeof(a));
for(int i=0;i<n;i++)
{
int val;
read(val);
if(vis[val]==-1)
cnt++;
else
a[vis[val]]++;
}
printf("Case #%d: ",cas++);
solve();
}
return 0;
}