/*题目描述:-----------------------------------------------------------------------------------------------*/
大话西游与数字游戏
“叉烧鸡翅膀,我呀最爱吃!……”
百度spider组的“黑龙潭之行”在烤着鸡翅,唱着星爷的经典时达到高潮。大家在篝火旁围成一圈,开始玩“数7”加强版游戏,规则如下:
规则1:遇7的倍数或含7的数时pass。
规则2:遇有包含相同数字的数时pass。注意相同数字不必相邻。例如121。
数错的惩罚很残酷——吞食烤全羊。为避免惩罚,百度工程师们需要你——史上最强程序员的帮助。百度工程师想知道:
req1 x:符合规则1的第x个数是什么?
req2 y:符合规则2的第y个数是什么?
req12 z:同时符合规则1、2的第z个数是什么?
query n:数n是规则1中的第几个数,是规则2中的第几个数?
输入格式
输入的每一行为一个查询,由一个查询词和一个无符号整型数组成。共有四种查询,查询词分别为req1、req2、req12、query(区分大小写)。
输出格式
前三种查询输出一个无符号整型的解。对于“query n”的查询,若n是规则中的数则输出相应的解,否则输出-1。
输入样例
req1 10
req2 10
req12 10
query 14
输出样例
11
10
12
-1 13
/*算法描述与分析-----------------------------------------------------------------------------------------------*/
前三个问题,采用动态规划法,先定位最高位,再依次从高位到低位,搜索每一位的数字,算法复杂度为O(K*logN),
K是常数,N为输入数字。第四个问题采用数字的二分查找,O(logN*lgN),前者以10为底,后者以2为底。每个问题的思路为:
1、问题1使用req1arr[10][10][7],req1arr[i][j][k]表示最高位为j的,长度为i(10进制)的正整数中,整除7余k的数有多少个。
时间复杂度O(70*logN),空间复杂度O(700)。
2、问题2不使用而外数组,只是为了提高效率将n!预先存入fac[n]。时间复杂度O(10*logN),空间复杂度O(1)。
3、问题3使用nums[10][11][7],digits[10][10][7],compose[1024][7],compose_digits[1024]。nums[i][j][k]表示最高位为j的,
长度为i的,满足规则2的,不含有7的数字中,整除7余k的数有多少个。digits[i][j][k]表示长度为i的,满足规则2的,不含有7的,
含有数字j的数有多少个。compose[i][k]表示,将i的二进制数中1对应的位数所组成的排列中,整除7余k的数有多少个。
compose_digits[i]表示i中有几个1。时间复杂度O(70000*logN*logN),空间复杂度O(7000)。
4、问题4使用数字的二分查找。left=0,right=N,然后计算(left+right)/2,直到找到,或left=right。
/*源代码-------------------------------------------------------------------------------------------------------*/
源代码中包括三块:1、本算法的源代码;2、另一种算法(逐一数)的源代码;3比较测试代码。
当数字较大时,本算法的优势明显。
#include <vector>
#include <string>
#include <iostream>
using namespace std;
#define tp 0
static const unsigned int ten[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
static const unsigned int fac[12]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800};
/*******************************************class define req*******************************/
class req{
protected:
unsigned int highdigit, val_b, val_c, ret;
virtual int init();
virtual int dpinit()=0;
virtual int dparray(unsigned int d)=0;
virtual unsigned int searchdigit(unsigned int& value, unsigned int d)=0;
virtual int test_print()=0;
public:
unsigned int searchnumber(unsigned int value);
};
/*******************************************class define req1*******************************/
class req1:public req{
protected:
unsigned int req1arr[10][10][7];
int dpinit();
int dparray(unsigned int d);
unsigned int searchdigit(unsigned int& value, unsigned int d);
int test_print(){return 1;}
public:
req1();
};
/*******************************************class define req2*******************************/
class req2:public req{
protected:
unsigned int digit;
int init();
int dpinit();
int dparray(unsigned int d);
unsigned int searchdigit(unsigned int& value, unsigned int d);
int test_print(){return 1;}
public:
};
/*******************************************class define req12*******************************/
class req12:public req{
unsigned int nums[10][11][7],digits[10][10][7],compose[1024][7],compose_digits[1024],digit;
int init();
int dpinit();
int dparray(unsigned int d);
unsigned int searchdigit(unsigned int& value, unsigned int d);
int test_print();
public:
req12();
};
/*******************************************class define query*******************************/
class query{
public:
req1 *preq1;
req2 *preq2;
int searchnumber(unsigned int value);
};
/*******************************************class define baiduwest*******************************/
class baiduwest{
req1 oreq1;
req2 oreq2;
req12 oreq12;
query oquery;
public:
baiduwest(){oquery.preq1=&oreq1;oquery.preq2=&oreq2;}
int searchnumber(unsigned int value, unsigned int type);
};
/*******************************************class employ req*******************************/
int req::init(){
highdigit=0;val_b=0;val_c=0;ret=0;
return 1;
}
unsigned int req::searchnumber(unsigned int value){
unsigned int i,j;
//initial
init();
//search highest digit
for(i=1;i<10;i++){
dparray(i);
if(searchdigit(value,i)!=10) break;
}
if(highdigit==0) return 0;
//search from highest-1 digit
for(i=highdigit-1;i>0;i--){
dpinit();
for(j=1;j<=i;j++)
dparray(j);
searchdigit(value,i);
}
return ret;
}
/*******************************************class employ req1*******************************/
req1::req1(){
memset(req1arr, 0 ,sizeof(req1arr));
req1arr[0][0][0]=1;
}
int req1::dpinit(){
return 1;
}
int req1::dparray(unsigned int d){
unsigned int j,k,t;
for(j=0,t=0;j<7;j++)
t+=req1arr[d][0][j];
if(t) return 1;
for(j=0;j<10;j++)
for(k=0;k<7;k++)
req1arr[d][0][k]+=req1arr[d-1][j][k];
for(j=1;j<10;j++){
if(j==7) continue;
t=(j*ten[d-1])%7;
for(k=0;k<7;k++){
req1arr[d][j][(t+k)%7]+=req1arr[d][0][k];
}
}
return 1;
}
unsigned int req1::searchdigit(unsigned int& value, unsigned int d){
int j,k,t;
t=ret%7;
val_b=0;
if(highdigit) j=0;
else j=1;
for(;j<10;j++){
if (j==7) continue;
for(k=0,val_c=0;k<7;k++)
if((t+k)%7) val_c+=req1arr[d][j][k];
if((val_b<value)&&(value<=val_b+val_c)){
if(highdigit==0) highdigit=d;
value-=val_b;
ret+=j*ten[d-1];
return j;
}
val_b+=val_c;
}
value-=val_b;
return j;
}
/*******************************************class employ req2*******************************/
int req2::init(){
req::init();
digit=0;
return 1;
}
int req2::dpinit(){
return 1;
}
int req2::dparray(unsigned int d){
return 1;
}
unsigned int req2::searchdigit(unsigned int& value, unsigned int d){
unsigned int j,t;
//cout<<"req2::searchdigit d:"<<d<<" value:"<<value<<endl;
for(j=0,t=0;j<10;j++)
if((digit&(1<<j))==0) t++;
val_b=0;
if(highdigit) j=0;
else j=1;
for(;j<10;j++){
if(digit&(1<<j)) continue;
val_c=(fac[t-1]/fac[t-d]);
if((val_b<value)&&(value<=val_b+val_c)){
if(highdigit==0) highdigit=d;
value-=val_b;
ret+=j*ten[d-1];
digit|=1<<j;
return j;
}
val_b+=val_c;
}
value-=val_b;
return j;
}
/*******************************************class employ req12*******************************/
int req12::test_print(){
unsigned int i,j,k;
if(tp) return 1;
for(i=0;i<10;i++){
cout<<i<<":"<<endl;
for(j=0;j<10;j++){
cout<<j<<"(";
for(k=0;k<7;k++)
cout<<nums[i][j][k]<<",";
cout<<")";cout<<endl;
}
}
cout<<"digit:"<<digit<<" highdigit: "<<highdigit<<endl;
return 1;
}
req12::req12(){
memset(compose_digits,0,sizeof(compose_digits));
unsigned int i,t,c;
for(i=1;i<1024;i++){
t=i;c=0;
while(t){t&=t-1;c++;}
compose_digits[i]=c;
}
}
int req12::dpinit(){
memset(nums,0,sizeof(nums));
nums[0][10][0]=1;
memset(digits,0,sizeof(digits));
memset(compose,0,sizeof(compose));
compose[0][0]=1;
return 1;
}
int req12::init(){
req::init();
digit=1<<7;
dpinit();
return 1;
}
int req12::dparray(unsigned int d){
unsigned int j,k,m,t,tm,t_sum[7];
memset(t_sum,0,sizeof(t_sum));
//computer nums[d][j][k]
for(j=0;j<10;j++){
if(digit&(1<<j)) continue;
t=(j*ten[d-1])%7;
for(k=0;k<7;k++){
nums[d][j][(t+k)%7]+=nums[d-1][10][k];
nums[d][j][(t+k)%7]-=digits[d-1][j][k];
}
for(k=0;k<7;k++)
t_sum[k]+=nums[d][j][k];
}
//nums[d][10][k]
for(k=0;k<7;k++)
nums[d][10][k]=t_sum[k];
//compose[]
for(m=0;m<1024;m++){
if(compose_digits[m]!=d-1) continue;
for(j=0;j<10;j++){
if((digit&(1<<j))||(m&(1<<j))) continue;
tm=(1<<j)|m;
t=(j*ten[d-1])%7;
for(k=0;k<7;k++){
compose[tm][(t+k)%7]+=compose[m][k];
}
}
}
//digits[d][j][k]
for(m=0;m<1024;m++){
if(compose_digits[m]!=d) continue;
for(j=0;j<10;j++){
if((digit&(1<<j))||!(m&(1<<j))) continue;
for(k=0;k<7;k++)
digits[d][j][k]+=compose[m][k];
}
}
return 1;
}
unsigned int req12::searchdigit(unsigned int& value, unsigned int d){
unsigned int j,k,t;
t=ret%7;
val_b=0;
if(highdigit) j=0;
else j=1;
for(;j<10;j++){
if(digit&(1<<j)) continue;
for(k=0,val_c=0;k<7;k++)
if((t+k)%7) val_c+=nums[d][j][k];
if((val_b<value)&&(value<=val_b+val_c)){
if(highdigit==0) highdigit=d;
value-=val_b;
ret+=j*ten[d-1];
digit|=1<<j;
return j;
}
val_b+=val_c;
}
value-=val_b;
return j;
}
/*******************************************class employ query*******************************/
int query::searchnumber(unsigned int value){
unsigned int i,obj=0,t;
unsigned int left,right,now;
int res[2];
req* areq[2];
areq[0]=preq1;
areq[1]=preq2;
res[0]=0;res[1]=0;
if(!(value%7)) res[0]=-1;
for(i=0;i<10;i++){
if(value<ten[i]) break;
t=(value/ten[i])%10;
if(t==7) res[0]=-1;
if ((1<<t)&obj) {res[1]=-1;break;}
obj|=(1<<t);
}
for(int i=0;i<2;i++){
if(res[i]==-1) continue;
left=1;right=value;
cout<<"query "<<i<<endl;
while(left!=right){
now=(left+right)>>1;
t=areq[i]->searchnumber(now);
if(t==value){res[i]=now;break;}
else if(t==0){right=now-1;}
else if(t<value)left=now+1;
else right=now-1;
}
if(left==right) res[i]=left;
}
//cout<<"query ok"<<endl;
cout<<res[0]<<" "<<res[1]<<endl;
return 1;
}
/*******************************************class employ baiduwest*******************************/
int baiduwest::searchnumber(unsigned int value, unsigned int type){
if(type==1){cout<<oreq1.searchnumber(value)<<endl;}
if(type==2){cout<<oreq2.searchnumber(value)<<endl;}
if(type==3){cout<<oreq12.searchnumber(value)<<endl;}
if(type==4){oquery.searchnumber(value);}
return 1;
}
/****************************************class test*****************************************/
bool IncludeOrModSevenu(unsigned int cinn){
if(cinn==0) return false;
if(cinn%7==0) return true;
unsigned int temp;
while (cinn){
temp=cinn%10;
if(temp==7) return true;
cinn/=10;
}
return false;
}
bool HaveSameNumn(unsigned int cinn){
unsigned int record[10];
memset(record,0,sizeof(record));
while(cinn){
record[cinn%10]++;
cinn/=10;
}
for(int i=0;i<10;i++)
if(record[i]>1) return true;
return false;
}
int baidustar20070104_test(int type, int value){
int cinn,num,j=0;
cinn=value;
if (type==1){
num=0; j=0;
while(1){
j++;
if(!IncludeOrModSevenu(j)) num++;
if(num==cinn){
break;
}
}
}
if(type==2){
num=0;j=0;
while(1){
j++;
if(!HaveSameNumn(j)) num++;
if(num==cinn){
break;
}
}
}
if(type==3){
num=0;j=0;
while(1){
j++;
if((!HaveSameNumn(j))&&(!IncludeOrModSevenu(j))) num++;
if(num==cinn){
break;
}
}
}
if(type==4){
num=0;j=0;
if (IncludeOrModSevenu(cinn)) j=-1;
else{
while(1){
j++;
if(!IncludeOrModSevenu(j)){
num++;
if(j==cinn){
j=num;
break;
}
}
}
}
}
if(type==5){
num=0;j=0;
if (HaveSameNumn(cinn)) j=-1;
else{
while(1){
j++;
if(!HaveSameNumn(j)){
num++;
if(j==cinn){
j=num;
break;
}
}
}
}
}
return j;
}
/***************************************************************************/
int doit(){
baiduwest* a=new baiduwest();
int value[]={109,1342,53214,230000,-1};
int i;
for(i=0;i<20;i++){
if(value[i]==-1) break;
cout<<"i: "<<i<<" value:"<<value[i]<<endl;
a->searchnumber(value[i],3);
cout<<"test: "<<baidustar20070104_test(3,value[i])<<endl;
cout<<endl;
}
return 1;
}
2007年百度之星程序设计大赛初赛试题与解答 第1场 大话西游与数字游戏
最新推荐文章于 2018-10-17 12:52:59 发布