Codeforces 525E Anya and Cubes

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

题意:

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

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

 #include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#define ll long long
struct node{
ll v,st;
int id,y;
}b[],c[];
int tot1,tot2;
int n,K,flag,a[],d[];
ll S,bin[],jc[],ans;
bool cmp(node a,node b){
return a.v<b.v;
}
ll read(){
ll t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
int lowbit(int x){
return (x)&(-x);
}
bool pd(ll st1,ll st2){
int cnt=;
while (st1){
ll t=st1%;
if (t==) cnt++;
st1/=;
}
while (st2){
ll t=st2%;
if (t==) cnt++;
st2/=;
}
return cnt<=K;
}
void dfs(int k,ll st,ll res,int cnt,int lim){
if (k>lim){
if (flag==){
tot1++;
b[tot1].v=res;
b[tot1].st=st;
b[tot1].id=;
b[tot1].y=cnt;
}else{
tot2++;
c[tot2].v=res;
c[tot2].st=st;
c[tot2].id=;
c[tot2].y=cnt;
}
return;
}
dfs(k+,st+bin[k-]*,res,cnt,lim);
dfs(k+,st+bin[k-]*,res+a[k],cnt,lim);
if (a[k]<=&&res+jc[a[k]]<=S&&cnt+<=K)
dfs(k+,st+bin[k-]*,res+jc[a[k]],cnt+,lim);
}
int num(ll x){
int cnt=;
while (x){
ll t=x%;
if (t==) cnt++;
x/=;
}
return cnt;
}
void up(int x,int v){
for (int i=x;i<=K;i++)
d[i]+=v;
}
int ask(int x){
return d[x];
}
int main(){
n=read();K=read();S=read();
bin[]=;
for (int i=;i<=;i++)
bin[i]=bin[i-]*;
jc[]=;
for (int i=;i<=;i++)
jc[i]=jc[i-]*i;
for (int i=;i<=n;i++)
a[i]=read();
flag=;
dfs(,,,,(n+)>>);
flag=;
dfs(((n+)>>)+,,,,n);
std::sort(b+,b++tot1,cmp);
std::sort(c+,c++tot2,cmp);
int j=tot2;
for (int i=;i<=tot1&&j;){
for (;j&&b[i].v+c[j].v>S;j--);
if (b[i].v+c[j].v==S){
for (int y=;y<=K;y++) d[y]=;
for (;i<=tot1&&b[i].v+c[j].v==S;i++) d[b[i].y]++;
for (int y=;y<=K;y++) d[y]+=d[y-];
for (;j&&b[i-].v+c[j].v==S;j--) ans+=d[K-c[j].y];
}else i++;
}
printf("%I64d\n",ans);
return ;
}
上一篇:final+基本类型导致只编译常量类引起的错误


下一篇:Creating a Table View Programmatically