有趣的数

让我们来考虑1到N的正整数集合。让我们把集合中的元素按照字典序排列,例如当N=11时,其顺序应该为:1,10,11,2,3,4,5,6,7,8,9。

定义K在N个数中的位置为Q(N,K),例如Q(11,2)=4。现在给出整数K和M,要求找到最小的N,使得Q(N,K)=M。

输入输出格式

输入格式:

 

输入文件只有一行,是两个整数K和M。

 

输出格式:

 

输出文件只有一行,是最小的N,如果不存在这样的N就输出0。

 

对于一个k,一位数在它前面的数是固定的,两位数在它前面的数是固定的,可以计算

而且,在k之前的数至少有一个定值,这是n取到k就有的

所以只用计算大于k的情况

比如354

1000->3539

10000->35399

不要忘记m是第几位,而不是前几位

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long ll;
 8 const ll maxn=27;
 9 ll ans,k,m,len;
10 ll fa[maxn];
11 char s[maxn];
12 ll getnum(ll x){
13   sprintf(s,"%lld",x);
14   len=strlen(s);
15   ll num=0,ret=0;
16   for(ll i=0;i<len;i++){
17     num=num*10+s[i]-'0'; 
18     ret+=num-fa[i]+1; 
19   }
20   return ret;
21 }//这个方法要记住
22 int main(){
23   cin>>k>>m;
24   fa[0]=1;for(ll i=1;i<=20;i++) fa[i]=fa[i-1]*10;
25   for(ll i=0;i<=10;i++){
26     if(k==fa[i]){
27       if(m!=i+1){cout<<0<<endl;return 0;}
28       if(m==i+1){cout<<k<<endl;return 0;}
29     }
30   } 
31   ll tt=getnum(k);
32   if(tt>m){cout<<0<<endl;return 0;}
33   if(tt==m){cout<<k<<endl;return 0;}
34   m-=tt;ans=fa[len];
35   for(ll i=1;;i++){
36     ll t=k*fa[i]-1-fa[i+len-1]+1;
37     if(m>t){
38       m-=t;ans*=10;
39     }
40     else break;
41   }
42   ans+=m-1;cout<<ans<<endl;
43   return 0;
44 }

而我想到的打表,首先没有分析出k前面的数至少有一个定值的性质

并且还错误的认为m<k-1就不可能,事实上是有可能的,并且很可能

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long ll;
 8 const int maxn=107;
 9 ll n,m,k,tot,mm,ans;
10 ll num[maxn],cnt[maxn];
11 ll getnum(ll x){
12   int ret;
13   while(x){
14     x/=10;ret++;
15   }ret--;
16   return ret;
17 }
18 ll qpow(ll a,ll b){
19   ll ret=1;
20   for(;b;b>>=1,a*=a){
21     if(b&1) ret*=a;
22   }
23   return ret;
24 }
25 void gettable(){
26   ll tmp=1;
27   for(ll i=1;i<=19;i++){
28       if(i==mm){
29       num[i]=k/(qpow(10,mm-i))-1;
30       cnt[i]=num[i]-tmp+1;   
31     }
32     else if(tmp<k){
33       num[i]=k/(qpow(10,mm-i));
34       cnt[i]=num[i]-tmp+1;
35     }
36     else{
37       num[i]=num[i-1]*10+9;
38       cnt[i]=num[i]-tmp+1;
39     }
40     tmp*=10;
41   }
42 }
43 int main(){
44   cin>>k>>m;
45   if(m<k-1){cout<<0<<endl;return 0;}
46   mm=getnum(k);
47   if(k==qpow(10,mm-1)){
48     if(m==mm){cout<<k<<endl;return 0;}
49     else{cout<<0<<endl;return 0;}
50   }
51   gettable();
52   ll tmp=1;m--;
53   for(int i=1;i<=19;i++){
54     if(m>cnt[i]){m-=cnt[i];ans=num[i];}
55     else{
56       ans=tmp+m-1;break;
57     }
58     tmp*=10;
59   }
60   cout<<ans<<endl;
61   return 0;
62 } 

这个又超时有WA的,我的代码总是写得调不出来,

Think twice,code once 啊啊啊

posted @ 2018-10-20 15:39  lcan  阅读(381)  评论(0编辑  收藏  举报