Codeforces 525E Anya and Cubes

http://codeforces.com/contest/525/problem/E

题意:

有n个方块,上面写着一些自然数,还有k个感叹号可用。k<=n 
你可以选任意个方块,然后选一些贴上感叹号使上面的数值变成阶乘,然后把方块上的值加起来会得到一个和。 
求和等于S的选择方法数。 

思路:折半搜索,然后把所有状态按权值排序,然后统计

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<iostream>
  6 #define ll long long
  7 struct node{
  8     ll v,st;
  9     int id,y;
 10 }b[3000005],c[3000005];
 11 int tot1,tot2;
 12 int n,K,flag,a[200005],d[200005];
 13 ll S,bin[50],jc[50],ans;
 14 bool cmp(node a,node b){
 15     return a.v<b.v;
 16 }
 17 ll read(){
 18     ll t=0,f=1;char ch=getchar();
 19     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
 20     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
 21     return t*f;
 22 }
 23 int lowbit(int x){
 24     return (x)&(-x);
 25 }
 26 bool pd(ll st1,ll st2){
 27     int cnt=0;
 28     while (st1){
 29         ll t=st1%3;
 30         if (t==2) cnt++;
 31         st1/=3;
 32     }
 33     while (st2){
 34         ll t=st2%3;
 35         if (t==2) cnt++;
 36         st2/=3;
 37     }
 38     return cnt<=K;
 39 }
 40 void dfs(int k,ll st,ll res,int cnt,int lim){
 41     if (k>lim){
 42         if (flag==0){
 43             tot1++;
 44             b[tot1].v=res;
 45             b[tot1].st=st;
 46             b[tot1].id=0;
 47             b[tot1].y=cnt;
 48         }else{
 49             tot2++;
 50             c[tot2].v=res;
 51             c[tot2].st=st;
 52             c[tot2].id=1;
 53             c[tot2].y=cnt;
 54         }
 55         return;
 56     }
 57     dfs(k+1,st+bin[k-1]*0,res,cnt,lim);
 58     dfs(k+1,st+bin[k-1]*1,res+a[k],cnt,lim);
 59     if (a[k]<=19&&res+jc[a[k]]<=S&&cnt+1<=K)
 60     dfs(k+1,st+bin[k-1]*2,res+jc[a[k]],cnt+1,lim);
 61 }
 62 int num(ll x){
 63     int cnt=0;
 64     while (x){
 65         ll t=x%3;
 66         if (t==2) cnt++;
 67         x/=3;
 68     }
 69     return cnt;
 70 }
 71 void up(int x,int v){
 72     for (int i=x;i<=K;i++)
 73      d[i]+=v;
 74 }
 75 int ask(int x){
 76     return d[x];
 77 }
 78 int main(){
 79     n=read();K=read();S=read();
 80     bin[0]=1;
 81     for (int i=1;i<=20;i++)
 82      bin[i]=bin[i-1]*3;
 83     jc[0]=1;
 84     for (int i=1;i<=19;i++)
 85      jc[i]=jc[i-1]*i; 
 86     for (int i=1;i<=n;i++) 
 87       a[i]=read();
 88     flag=0;
 89     dfs(1,0,0,0,(n+1)>>1);
 90     flag=1;
 91     dfs(((n+1)>>1)+1,0,0,0,n);
 92     std::sort(b+1,b+1+tot1,cmp);
 93     std::sort(c+1,c+1+tot2,cmp);
 94     int j=tot2;
 95     for (int i=1;i<=tot1&&j;){
 96         for (;j&&b[i].v+c[j].v>S;j--);
 97         if (b[i].v+c[j].v==S){
 98             for (int y=0;y<=K;y++) d[y]=0;
 99             for (;i<=tot1&&b[i].v+c[j].v==S;i++) d[b[i].y]++;
100             for (int y=1;y<=K;y++) d[y]+=d[y-1];
101             for (;j&&b[i-1].v+c[j].v==S;j--) ans+=d[K-c[j].y];
102         }else i++;
103     }
104     printf("%I64d\n",ans);
105     return 0;
106 }

 

posted @ 2016-06-29 10:57  GFY  阅读(231)  评论(0编辑  收藏  举报