Rikka with Mista
时间限制: 7 Sec 内存限制: 512 MB
题目描述
Rikka is a fervent fan of JoJo’s Bizarre Adventure. As the last episode of Golden Wind has been aired, Rikka, with the help of Yuta, sets up this problem to express the love to Mista.
Mista’s lucky number is 4. Today, Mista wants to test his luck with n magic cards: For each card, there is a non-negative integer on each side. The two numbers on the ith card are wi and 0.
Firstly, Mista puts these n cards to table one by one. For each card, the probability of the wi side to be upward is 1/2, and these probabilities are independent with each other. As a result, there are n integers on the table. Mista then sums up all these integers and counts the number of 4s in the decimal representation of this sum: He uses this result to measure his luckiness.
Since it’s possible for each side of each card to be upward, there are 2n possible states in total. You are required to calculate the sum of the results for all these situations.
输入
The first line of the input contains a single integer T(4≤T≤4), the number of test cases.
For each test case, the first line contains a single integer n(4≤n≤40), the number of the cards.
The second line contains n integers w1,…,wn(4≤wi≤44444444), the positive numbers on the cards.
输出
For each test case, output a single line with a single integer, the answer.
样例输入
4
4
4 4 4 4
4
4 4 44 44
4
4 44 44 4444
4
444 44444 44444 4444444
样例输出
4
10
24
38
提示
There are 44 4s in the sample input. Mista would like this sample input.
In the first test case, there is 1 state with the sum equal to 0; 4 states with the sum equal to 4; 6 states with the sum equal to 8; 4 states with the sum equal to 12 and 1 state with the sum equal to 16.
Therefore, there are only 4 situations with the result equal to 1 while on other cases, the result is 0. So the answer should be 4.
方法
折半搜索+桶排序+双指针查找
n的个数为40,直接枚举会t,不难想到折半搜索的方法
然后依次按照每一位进行排序,使用双指针查找i+j在该位大于等于4小于5或者大于等于14小于15的情况
双指针可以使用是因为对于增加的i,符合条件的j是一个连续的区间,并且区间左右端点只可能左移而不会右移
对每一位排序的方法可以利用桶排序进行优化,省去一个log的复杂度
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=2048576+5;
const int M=400+5;
ll ans[5][N];
ll a[5][M];
ll tp[10][N]; //桶排
int n1,n2;
void dfs(ll* a,int i,ll now,int n,ll *ans,int &k)
{
if(i==n+1)
{
ans[++k]=now;
return;
}
dfs(a,i+1,now,n,ans,k);
dfs(a,i+1,now+a[i],n,ans,k);
}
void msort(ll *a,int n,ll p)
{
for(int i=0;i<=9;i++) tp[i][0]=0;
for(int i=1;i<=n;i++)
{
int x=(a[i]/p)%10;
tp[x][++tp[x][0]]=a[i];
}
n=0;
for(int i=0;i<=9;i++)
for(int j=1;j<=tp[i][0];j++)
a[++n]=tp[i][j];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _;
cin>>_;
while(_--){
int n;
cin>>n;
int m1=n/2;
int m2=n-m1;
for(int i=1;i<=m1;i++)
cin>>a[0][i];
for(int i=1;i<=m2;i++)
cin>>a[1][i];
n1=n2=0;
dfs(a[0],1,0,m1,ans[0],n1);
dfs(a[1],1,0,m2,ans[1],n2);
/*for(int i=1;i<=n1;i++)
cout<<ans[0][i]<<' ';
cout<<endl;
for(int i=1;i<=n2;i++)
cout<<ans[1][i]<<' ';
cout<<endl;*/
ll p=1,anss=0;
for(int ii=0;ii<=9;ii++,p*=10){
msort(ans[0],n1,p);
msort(ans[1],n2,p);
int l=n2,r=n2;
for(int i=1;i<=n1;i++){
while(l>=1&&(ans[0][i]%(p*10)+ans[1][l]%(p*10)>=4*p)) l--;
while(r>=1&&(ans[0][i]%(p*10)+ans[1][r]%(p*10)>=5*p)) r--;
anss+=r-l;
}
l=n2,r=n2;
for(int i=1;i<=n1;i++){
while(l>=1&&(ans[0][i]%(p*10)+ans[1][l]%(p*10)>=14*p)) l--;
while(r>=1&&(ans[0][i]%(p*10)+ans[1][r]%(p*10)>=15*p)) r--;
anss+=r-l;
}
}
cout<<anss<<endl;
}
}