您的位置:首页 > 其它

牛客练习赛13 幸运数系列

2018-03-18 01:24 1776 查看
***个人认为这4题出的相当好! 
定义:   一个数的数位上数字均是4或7,称为‘幸运数’;
幸运数字I

题意:求出字符串s的出现最多次数的幸运子串,有多个,求字典序最小的。
任何幸运数都由4和7组成,考虑字典序最小,满足题意的幸运子串的长度为1;
例:44由4构成,4出现一定不小于其2倍;77同理;47由4和7组成,4出现的次数不小于47,且4的字典序小于7、47;

所以有答案一定是4或者7;
   num_4==0&&num_7==0,  无幸运数,输出“-1”;
   num_4>=num_7,输出"4";
   num_4 < num_7,输出"7";#include <iostream>
#include <string.h>
using namespace std;

int main()
{
string s;
cin>>s;
int a=0,b=0;
for(int i=0;i<s.length();++i)
if(s[i]=='4')++a;
else if(s[i]=='7')++b;

if(a==0&&b==0)cout<<-1<<endl;
else if(a>=b){
cout<<4<<endl;
}else {
cout<<7<<endl;
}
return 0;
}

幸运数字II

题意:定义next(x)不小于x的第一个幸运数字,求区间[l,r]内所有数的next的和;(r<=1e9)
千万不要走进数位dp的坑!
不大于next(1e9)的幸运数的个数不超过1050个!  记ai为所有4位数的幸运数的个数,a1=2;
ai+1  =    ai  (第i+1位放4) +  ai  (第i+1位放7),得ai=2^i,  Si=2^(i+1)-2;(i<=9)
*按升序顺序求出Si个幸运数
  (可以将ai中所有数字的第i+1位上添4,在添7);
   但从Code的角度来说,将ai中每个数字乘10在分别加4、7更加合适!
*遍历ai,调整l,找出区间中next(x)=ai,x的个数,并调整区间左端点l=ai+1;#include <iostream>
#include <string.h>
#include <vector>
#define llt long long
using namespace std;

int main()
{
llt l,r;
cin>>l>>r;
vector<llt> V;
V.push_back(4);V.push_back(7);
for(int i=2;i<=10;++i){
for(int j=(1<<(i-1))-2;j<(1<<i)-2;++j){
V.push_back(V[j]*10+4);
V.push_back(V[j]*10+7);
}
}
llt ans=0;
for(int i=0;i<V.size();++i){
//if(l>=r)break;
if(V[i]<l)continue;

if(V[i]>=r){ans+=(r-l+1)*V[i];break;}
ans+=V[i]*(V[i]-l+1);
l=V[i]+1;
}

cout<<ans<<endl;
return 0;
}
幸运数字III
题意:数字字符串d1d2……dn,对其进行k次操作,每次操作:找出最左侧的dxdx+1="47";
          *x为奇数,将dxdx+1变为“44”
          *x为偶数,将dxdx+1变为“77”
 输出最后的字符串;
遍历字符串,遇到di=‘4’,即测试一下di+1是否为‘7’,如果不为‘7’,即继续遍历;如果di+1==‘7’:
讨论:i为奇数,将di+1变为‘4’,继续向下遍历;
          i为偶数,将di变为‘7’,di-1为‘7’,继续向下遍历,如果di-1为‘4’,(i-1奇、i偶、i+1奇)
          那么477-->447--->477--->447,操作会在此处以2循环下去,仅需判断此时k的奇偶,k为偶不变,k为奇仅操作1次;
时间复杂度变为O(len)非O(k)!#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#define llt long long
using namespace std;

char s[100010];
int main()
{
int n,k;
cin>>n>>k;

scanf("%s",s);

int l=1;
while(k){
if(l>=n){break;}
if(s[l-1]!='4'||s[l]!='7'){++l;continue;}

--k;
if(l%2==1) {s[l]='4';++l;continue;}
s[l-1]='7';

if(s[l-2]=='4'){
if(k%2){s[l-1]='4';}
break;
}
}
printf("%s",s);

}幸运数字IV
题意:数字1……n的第k小排序中,数字即其位置均为幸运数字的个数;(k<=1e9)
          如果n!<k,输出-1!
1e9 对n!来说是个小数字,13!>k;  n很大时,前面1……(n-13)的顺序不变,我们考虑的仅仅是13个数字的顺序!
***求出1……13的阶乘a;将需要排序的最后数字放入b数组;
***如果n>13的话,我们需要求出前n-13个数字中幸运数字的个数,将r=n-13的所有数位求出,最高位temp-1为0的
     幸运数个数S=2^temp-2;ans+=S;下面的所有幸运数中不能在有数位0!只允许4和7!
从高位i开始,dight[i]<4 ,return;  (第i位不能取到4或7,结束!)
                   dight[i]==4,  ans+=(i==0),继续遍历,(i==0,即结束了遍历,前面数位和最后的数位均为4和7,即r为幸运数)
                   ans+=2^i(即第i位为4,其它数位任取4和7,幸运数的个数)
                   dight[i]<7(第i位不能取到'7',结束!)
                   dight[i]==7,  ans+=(i==0),继续遍历,(i==0,即结束了遍历,前面数位和最后的数位均为4和7,即r为幸运数)
                   ans+=2^i(即第i位为7,其它数位任取4和7,幸运数的个数)
                   return;(已经讨论完全,第i位为8、9绝对不是幸运数)
 ***对剩下的数进行排序,如果(i-1)*a[len-1]<k<=i*a[len-1],即此时因排bi于此时首位!将bi删去,len减1,
      k-=(i-1)*a[len-1];        判断 :bi和其位置start是否都是幸运数,是,ans++;直到len为0,就结束!

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#define llt long long
#define Size 100010
using namespace std;

int a[15];
int b[15];
int n,k,start,len;
int ans=0;

bool isUNF(int x){
while(x){
if(x%10!=4&&x%10!=7)return false;
x/=10;
}
return true;
}

void Havenum(int x){
int dight[12];
int temp=0;
while(x){
dight[temp++]=x%10;
x/=10;
}

ans=(1<<temp)-2;

for(int i=temp-1;i>=0;--i){
//printf("%d\n",ans);
if(dight[i]<4)return;
if(dight[i]==4){ans+=(i==0);continue;}
ans+=(1<<i);
if(dight[i]<7) return;
if(dight[i]==7){ans+=(i==0);continue;}
ans+=1<<i;
return ;
}
}
void init(){
a[0]=1;
for(int i=1;i<=13;++i)
a[i]=a[i-1]*i;
//printf("%d\n",a[13]);
start=1;
if(n>13){
start=n-12;
Havenum(n-13);
}
len=0;
for(int i=start;i<=n;++i) b[++len]=i;
}

void Delete(int x){
for(int i=x;i<len;++i) b[i]=b[i+1];
--len;
}
int main()
{
scanf("%d%d",&n,&k);
init();
if(n<=13&&k>a
) printf("-1\n");

else{
//printf("%d\n",ans);
while(start
4000
<=n){
int i;
for(i=1;;++i) if(k<=i*a[len-1])break;
k-=(i-1)*a[len-1];
if(isUNF(start)&&isUNF(b[i]))++ans;
Delete(i);
++start;
}

printf("%d\n",ans);
}
return 0;
}



  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  牛客赛 幸运数