題意:給你一個集合,求它的所有子集的子集和中數字4出現了多少次
例如
4
4 4 44 44
中4(1),4(2),44(3),44(4),48(1,3),48(1,4),48(2,3),48(2,4),總共有10個數字4
?
思路:
明顯數據范圍就是要拆開來做,先將子集盡可能平均分
這樣就有兩個大小不超過220的子集和集合。
考慮集合里所有數字的每一位對答案的貢獻
只有兩種可能,一種是當前位數兩位相加沒有進位,一種是當前位數兩位相加有進位
分別統計就是答案
而如果將當前位之后的那一部分數字從小到大有序排列好,就可以用兩個指針分別從兩邊去掃
然而直接排序會超時
所以考慮類似于歸并的思想,轉移時候將當前位拆開按順序重新丟入大集合里
就可以保證答案的正確性了
注意卡常
1 #include<bits/stdc++.h> 2 #define pb push_back 3 using namespace std; 4 int read(){ 5 int x=0,f=1;char c=getchar(); 6 for(;!isdigit(c);c=getchar())if(c=='-')f=-1; 7 for(;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+(c^48); 8 return x*f; 9 } 10 typedef long long ll; 11 struct data{ll fi,se;}; 12 data mp(ll a,ll b){ 13 data ret; 14 ret.fi=a;ret.se=b; 15 return ret; 16 } 17 typedef data pll; 18 int n,li[50]; 19 vector<pll> X,Y,A[10],B[10]; 20 21 void get_X(int dep,ll sum){ 22 if(dep>(n/2)){X.pb(mp(sum,0));return;} 23 get_X(dep+1,sum);get_X(dep+1,sum+li[dep]); 24 } 25 void get_Y(int dep,ll sum){ 26 if(dep>n){Y.pb(mp(sum,0));return;} 27 get_Y(dep+1,sum);get_Y(dep+1,sum+li[dep]); 28 } 29 30 ll get0(vector<pll> &a,vector<pll> &b,ll Base){ 31 ll ret=0;int p=b.size()-1; 32 for(int i=0;i<a.size();ret+=p+1,++i) 33 for(;p>=0&&b[p].se+a[i].se>=Base;--p); 34 return ret; 35 } 36 ll get1(vector<pll> &a,vector<pll> &b,ll Base){ 37 ll ret=0;int p=0; 38 for(int i=a.size()-1;~i;ret+=b.size()-p,--i) 39 for(;p<b.size()&&b[p].se+a[i].se<Base;++p); 40 return ret; 41 } 42 43 void solve(){ 44 X.clear();Y.clear(); 45 46 n=read(); 47 for(int i=1;i<=n;++i)li[i]=read(); 48 get_X(1,0);get_Y(n/2+1,0); 49 //get two set 50 ll ans=0,Base=1,tmp; 51 pll x,y,a,b; 52 for(int i=0;i<11;++i,Base*=10){ 53 for(int j=0;j<10;++j)A[j].clear(),B[j].clear(); 54 55 for(int j=0;j<X.size();++j) 56 x=X[j],A[x.fi%10].pb(mp(x.fi/10,x.se)); 57 for(int j=0;j<Y.size();++j) 58 y=Y[j],B[y.fi%10].pb(mp(y.fi/10,y.se)); 59 //get this digit 60 for(int j=0,k;j<10;++j){ 61 k=(14-j)%10; 62 ans+=get0(A[j],B[k],Base); 63 k=(13-j)%10; 64 ans+=get1(A[j],B[k],Base); 65 } 66 //Calc the ans 67 for(int j=0,now=0;j<10;++j){ 68 tmp=Base*j; 69 for(int k=0;k<A[j].size();++k) 70 a=A[j][k],X[now++]=mp(a.fi,a.se+tmp); 71 } 72 for(int j=0,now=0;j<10;++j){ 73 tmp=Base*j; 74 for(int k=0;k<B[j].size();++k) 75 b=B[j][k],Y[now++]=mp(b.fi,b.se+tmp); 76 } 77 } 78 printf("%lld\n",ans); 79 } 80 81 int main(){ 82 for(int T=read()+1;--T;)solve(); 83 return 0; 84 }
?