补题向 | The Wu(预处理,十进制二进制转换)

D. The Wu

#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<fstream>
#include<math.h>
#include<stack>
#include<bitset>
#include<utility>
using namespace std;
typedef long long ll;
const double eps=0.0000000000001;
int n,m,q;
int cm;
int w[15];
char s[5000][15];//存储不重复的s(最长12位,转换为十进制最长且最大序列值为4096) 
int sum[5000][105];//n长度的每个可能的序列所求值<=k的个数 
int cn[5000];//m太大,会超时,存相同的s个数

int mypow(int a){
	//计算2的a次方 
	int ans=1;
	for(int i=1;i<=a;i++){
		ans*=2;
	}
	return ans;
}
int cg(char*c){
	//二进制转十进制 
	int a=c[0]-'0';
	for(int i=1;i<n;i++){
		a*=2;
		a+=(c[i]-'0');
	}
	return a;
}
void bg(int it,char*c){
	//十进制转二进制 
	int i=n-1;
	while(i>=0){
		if(it==0){
			c[i]='0';
		}
		else c[i]=it%2+'0';
		it/=2;
		i--;
	}
}
void cal(int k){
	char t[12]={'0'};
	bg(k,t);
		for(int j=0;j<cm;j++){
			int p=0;
			for(int l=0;l<n;l++){
				if(s[j][l]==t[l]){
					p+=w[l];
				}
			}
			if(p<=100)sum[k][p]+=cn[cg(s[j])];
			//!!!虽然k<=100,实际算出来的数会超过(第20个测试点) 
		}
}
void init(){
	//预处理 
	memset(sum,0,sizeof(sum));	
	int k=0;
	for(;k<=mypow(n)-1;k++){
		cal(k);		
	}
	for(int i=0;i<=k+1;i++){
		for(int j=1;j<=100;j++){
			sum[i][j]+=sum[i][j-1];
		}
	}
}
int main(){
	while(~scanf("%d%d%d",&n,&m,&q)){
		for(int i=0;i<n;i++){
			scanf("%d",&w[i]);
		}
		memset(cn,0,sizeof(cn));
		cm=0;
		for(int i=0;i<m;i++){
			scanf("%s",&s[cm]);
			if(cn[cg(s[cm])]==0){
				cn[cg(s[cm])]++;
				cm++;
			}
			else cn[cg(s[cm])]++;
		}
		init();
		char t[15];
		int k;
		for(int l=0;l<q;l++){
			scanf("%s",&t);			
			scanf("%d",&k);			
			printf("%d\n",sum[cg(t)][k]);
		}
	}
    
	return 0;
}

感觉二进制和十进制转换和预处理还是用了很多时间,其他大大运行时间少很多,但是骚操作無理啊

猜你喜欢

转载自blog.csdn.net/bekote/article/details/81545702
今日推荐