hdu 4945 DP

//代码1:
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
#include <cassert>
#include <complex>
using namespace std;
#define rep(i,a,n) for (int i=a;i<(int)n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define ACCU accumulate
#define TWO(x) (1<<(x))
#define TWOL(x) (1ll<<(x))
#define clr(a) memset(a,0,sizeof(a))
#define POSIN(x,y) (0<=(x)&&(x)<n&&0<=(y)&&(y)<m)
#define PRINTC(x) cout<<"Case #"<<++__<<": "<<x<<endl 
#define POP(x) (__builtin_popcount(x))
#define POPL(x) (__builtin_popcountll(x))
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long ll;
typedef long double LD;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef vector<ll> VL;
typedef vector<PII> VPII;
typedef complex<double> CD;
const int inf=0x20202020;
const ll mod=998244353;
const double eps=1e-9;
const double pi=3.1415926535897932384626;
const int DX[]={1,0,-1,0},DY[]={0,1,0,-1};
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
// head

int cnt[3010];
ll f[101000],g[101000];
int pn,n,__;
int dp[13][3010];
inline int getint() {
    int ret=0;bool ok=0;
    for(;;) {
        int c=getchar();
        if(c>='0'&&c<='9')ret=(ret<<3)+ret+ret+c-'0',ok=1;
        else if(ok)return ret;
    }
}
int binom(int x,int y) {
    if (x<y||y<0) return 0;
    else return f[x]*g[y]%mod*g[x-y]%mod;
}
inline void upd(int &a,int b) { a+=b; if (a>=mod) a-=mod;}
int main() { 
    f[0]=1; rep(i,1,100001) f[i]=f[i-1]*i%mod;g[100000]=powmod(f[100000],mod-2);
    per(i,0,100000) g[i]=g[i+1]*(i+1)%mod;
    while (1) {
        n=getint();
        if (n==0) break;
        rep(i,0,12) cnt[TWO(i)]=0;
        rep(i,0,n) cnt[getint()]++;
        pn=0;
        rep(i,0,12) pn+=cnt[TWO(i)];
        rep(i,0,11) rep(j,0,TWO(10-i)) dp[i][j]=0; dp[11][0]=0;
        int ct=cnt[1];
        ll cof=f[ct];
        rep(j,0,TWO(11)) {
            if (j>ct) break;
            upd(dp[0][j>>1],g[ct-j]%mod*g[j]%mod);
        }
        rep(i,0,11) {
            ct=cnt[TWO(i+1)];
            cof=cof*f[ct]%mod;
            rep(j,0,TWO(10-i)) if (dp[i][j]) {
                rep(k,0,TWO(10-i)) {
                    if (k>ct||j+k>TWO(10-i)) break;
                    upd(dp[i+1][(j+k)>>1],1ll*dp[i][j]*g[k]%mod*g[ct-k]%mod);
                }
            }
        }
        int ans=(powmod(2,pn)-dp[11][0]*cof)%mod*powmod(2,n-pn)%mod;
        if (ans<0) ans+=mod;
        printf("Case #%d: %d\n",++__,ans);
    }
}



//代码2:
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <sstream>
#include <algorithm>
#include <numeric>
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define sqr(x) ((x)*(x))
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long ll;
template<typename X> inline bool minimize(X&p,X q){if(p<=q)return 0;p=q;return 1;}
template<typename X> inline bool maximize(X&p,X q){if(p>=q)return 0;p=q;return 1;}
const int mod = 998244353;
ll fac[100005],rf[1000005],CC[100005],SC[100005];

ll mpow(ll p,ll q){
    ll res=1;
    while(q){
        if(q&1)
            res=res*p%mod;
        q>>=1;
        p=p*p%mod;
    }
    return res;
}
ll C(int n,int m){return fac[n]*rf[m]%mod*rf[n-m]%mod;}
ll dp[15][2050];
int num[15],id[2050];
int main(){
    //freopen("1001.in","r",stdin);
    fac[0]=rf[0]=1;
    for(int i=1;i<=100000;++i){
        fac[i]=fac[i-1]*i%mod;
        rf[i]=mpow(fac[i],mod-2);
    }
    int N,cas=0;
    for(int i=0;i<2050;++i)id[i]=12;
    for(int i=0;i<12;++i)id[1<<i]=i;
    while(~scanf("%d",&N),N){
        memset(num,0,sizeof(num));
        for(int i=0,a;i<N;++i){
            scanf("%d",&a);
            ++num[id[a]];
        }
        memset(dp,0,sizeof(dp));
        ll ans=0;
        /*1要预处理好_begin*/
        for(int i=0;i<2048&&i<=num[0];++i)
            dp[0][i]=C(num[0],i);
        for(int i=2048;i<=num[0];++i)
            {ans+=C(num[0],i);
             ans %= mod;
            }
        /*1要预处理好_end*/
        for(int i=1;i<12;++i){
            int mm=2048>>i;
            ans=ans*mpow(2,num[i])%mod;
            ll s=0;
            for(int n=0,t=mm+mm;n<=num[i];++n){
                ll k=C(num[i],n);
                for(int j=0;j+n<mm;++j)
                    dp[i][j+n]=(dp[i][j+n]+k*(dp[i-1][j+j]+dp[i-1][j+j+1])%mod)%mod;
                if(k)ans=(ans+k*s)%mod;
                if(t){----t;s=(s+dp[i-1][t]+dp[i-1][t+1])%mod;}
            }
        }
        printf("Case #%d: %I64d\n",++cas,ans*mpow(2,num[12])%mod);
    }
    return 0;
}

//代码3
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#define pb push_back
#define mp make_pair
#define eps 1e-9
#define zero(x) (fabs(x)<eps)
#define pi acos(-1.0)
#define f1 first
#define f2 second
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define initial 1,n,1
const int inf=0x3f3f3f3f;
const long long INF=1LL<<50;
using namespace std;
typedef long long LL;
typedef pair <int, int> PII;
template<typename X> inline bool minimize(X&p,X q){if(p<=q)return 0;p=q;return 1;}
template<typename X> inline bool maximize(X&p,X q){if(p>=q)return 0;p=q;return 1;}
const LL mod=998244353;
#define N 2049
#define T 100005
int vis[N],n;
int tr[15],num[15];
LL fac[T],facc[T];
int f[13][N];
LL extend_gcd(LL a,LL b,LL &x,LL &y)
{
    if(a==0&&b==0) return -1;
    if(b==0){x=1;y=0;return a;}
    LL d=extend_gcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
LL quick(LL m,LL n,LL k)
{
    LL b = 1;
    while (n > 0)
    {
          if (n & 1)
             b = (b*m)%k;
          n = n >> 1 ;
          m = (m*m)%k;
    }
    return b;
}
inline int getint() {
    int ret=0;bool ok=0;
    for(;;) {
        int c=getchar();
        if(c>='0'&&c<='9')ret=(ret<<3)+ret+ret+c-'0',ok=1;
        else if(ok)return ret;
    }
}
void doit()
{   memset(f,0,sizeof(f));
    int tmp=0;
    int ans=0;
    memset(num,0,sizeof(num));
    for (int i=1,x;i<=n;i++)
        {   x=getint();
            if (vis[x]==-1) tmp++;else num[vis[x]]++;
        }
    f[12][0]=1;
    for (int i=11,x,need;i>=0;i--)
        {   x=tr[i];
            LL tmp;
            for (int k=2048,need=0,ss=0;;k-=x,need++)
                {   if (num[i]<need) break;
                    if (k>=0) ss=(ss+f[i+1][k])%mod;
                    if (need) {tmp=fac[num[i]]*facc[need]%mod*facc[num[i]-need]%mod;
                               ans=int((tmp*ss+ans)%mod);
                              }
                }
            if (i==0) break; //少这句时间差4倍
            for (int j=0;j<2048;j+=x)   if (f[i+1][j])
            for (int k=j,need=0;k<=2048;k+=x,need++)

                {   if (num[i]<need) break;
                    tmp=fac[num[i]]*facc[need]%mod*facc[num[i]-need]%mod;
                    f[i][k]=int((tmp*f[i+1][j]+f[i][k])%mod);
                }
            f[i][2048]=ans;
         }
    LL er=quick(2,tmp,mod);
    printf("%d\n",int(er*ans%mod));
}

void pre()
{   fac[0]=1;
    for (int i=1;i<=100000;i++)
        fac[i]=fac[i-1]*i%mod;
    for (int i=0;i<=100000;i++)
        facc[i]=quick(fac[i],mod-2,mod);
    memset(vis,255,sizeof(vis));
    tr[0]=1;vis[1]=0;for (int i=1;i<=11;i++){tr[i]=tr[i-1]*2;vis[tr[i]]=i;}
}
int main()
{   //freopen("1001.in","r",stdin);
    pre();
    int cas,id=0;
    while (scanf("%d",&n),n)
        {printf("Case #%d: ",++id);
         doit();
        }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值