让我们来考虑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 啊啊啊