现在有q个询问,每次询问想问你在[l,r]区间内,k进制表示中,k-1的数量最多的数是哪个数。比如当k=2时,9的二进制就是1001,那么他就有2个1.
现在有q个询问,每次询问想问你在[l,r]区间内,k进制表示中,k-1的数量最多的数是哪个数。比如当k=2时,9的二进制就是1001,那么他就有2个1.
第一行一个q,表示有q组询问。
接下来q行,每行三个整数k,l,r,分别表示进制数,查询的数字,以及查询的范围。
满足1<=q<=100000,2<=k<=16,1<=l<=r<=10^16
对于每组询问,输出答案。如果有多个答案,请输出最小的。
1 8 1 100
63
用java写的,最后还是通过了 但速度有点慢。这都不是关键,具体讲解一下思路。
首先将start(我用start和end分别表示左右的边界)转换成k进制。将转换后的每一位都存在arraylist中(数组和linklist也可以,自己选)。然后从低位往高位依次将每一位变成(k-1)。在变换之前,首先看看能不能变,能变则变,不能变表示超过了end,这个时候直接跳出即可。
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static long minNum(int k, long start, long end) {
ArrayList<Integer> list = new ArrayList<Integer>();
long tmp = start;
while (tmp != 0) {
long rest = tmp % k;
list.add((int) rest);
tmp = tmp / k;
}
long sum = 1;
for (int i = 0; i < list.size(); i++) {
long num = list.get(i);
num = k - 1 - num;
long size = (long) (num * sum);
if (start + size <= end) {
start = start + size;
} else {
return start;
}
sum = sum * k;
}
while (start < end) {
long size = (long) ((k - 1) * sum);
if (start + size <= end) {
start = start + size;
} else {
return start;
}
sum = sum * k;
}
return start;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int time = in.nextInt();
for (int i = 0; i < time; i++) {
int k = in.nextInt();
long start = in.nextLong();
long end = in.nextLong();
System.out.println(minNum(k, start, end));
}
}
}
}
q = int(input().strip())
# 将十进制转换为k进制,k进制的每一位,用列表中的一个数表示,注意当k 大于10时,k 进制中的每一位可能为两位数
def dec2k(dec):
ansk = []
while dec // k:
ansk.append(dec % k)
dec = dec // k
ansk.append(dec)
ansk = ansk[::-1]
return ansk
# 将k进制转换为十进制,k进制的每一位,用列表中的一个数表示,注意当k 大于10时,k 进制中的每一位可能为两位数
def k2dec(rans):
ansd = 0
tmp = 1
for i in range(len(rans)-1, -1, -1):
ansd += rans[i] * tmp
tmp *= k
return ansd
# k进制表示中,k-1的数量最多的数,且输出最小的,即k进制数每一位均为k-1构成
def get_ans():
if len(lvalue) == 0 or len(rvalue) == 0:
return
# 第一种全为(k-1), l <= and <= r
record, tmp = 0, 0
while tmp <= r:
record = tmp
tmp = tmp * k + (k-1)
# print("record:", record)
if record >= l:
return record
else:
''' # 每判断一下都需要进制转换,复杂度太高,超时,由于每次只更新一位,因此,可以直接修改
for i in range(len(lvalue)-1, -1, -1):
t = lvalue[i]
lvalue[i] = k-1
if k2dec(lvalue) > r: # 大于,则还原
lvalue[i] = t
return k2dec(lvalue)
'''
dec = k2dec(lvalue)
tmp = 1
for i in range(len(lvalue) - 1, -1, -1):
dec = dec + (k - 1 - lvalue[i]) * tmp
tmp = tmp * k
t = lvalue[i]
lvalue[i] = k - 1
if dec > r: # 大于,则还原
lvalue[i] = t
return k2dec(lvalue)
while q > 0:
k, l, r = map(int, input().strip().split())
lvalue = dec2k(l)
rvalue = dec2k(r)
print(get_ans())
q -= 1
'''
15
4 8442097414683844 8442097414683844
3 3173466882309064 3173466882309073
4 8527527027194177 8527527027194276
4 2661113491247500 2661113491248499
16 4448712248766526 4448712248776525
13 2684426398058983 2684426398158982
14 6562761408288807 6562761409288806
4 2847109288743406 2847109298743405
12 3011167199031338 3011167299031337
7 8655416323525458 8655417323525457
13 177186968879953 177196968879952
2 4133390730537405 4133490730537404
13 4680075382111731 4681075382111730
11 5341708995347620 5351708995347619
8 114951857079067 214951857079066
'''
您的代码已保存
运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
case通过率为86.67%
在本地跑,测试用例都通过了,不知道是哪里出现问题,我已经将原有的进制转换优化了,复杂度应该是O(n),难道真的是Python运行太慢了???有大佬麻烦指点一下,谢谢
#include <iostream>
#include <vector>
using namespace std;
// 思路 先把 low和high都转换成k进制数,然后寻找在[low, high]之间k进制中k-1最多的数,为方便k=10
// 123 123456 -> 099999:二者位数不同时, 把high最高位变成0,后面其他位置为9即可
// 123 999999 -> 999999 需要注意high所有位都为9时,ans = high, 玛德这种情况找了好久才找到,sad
// 123456 123556 -> 123499 二者位数相同时,把low从位数不同的下一位到最后置为9即可
// 123456 123999 -> 123999 需要注意high在不同位往后都为9时, ans = high
// 把number转换成k进制存在vector中,高位放在后面 如十进制的12345 -> 54321
void convertk(vector<int> &v, long number, int k) {
while (number) {
v.push_back(number % k);
number /= k;
}
}
long query(long low, long high, int k) {
if (low == high)
return low;
vector<int> vecLow, vecHigh, vecAns;
convertk(vecLow, low, k);
convertk(vecHigh, high, k);
int i = vecHigh.size()-1, j = vecLow.size()-1;
while (i == j && vecHigh[i] == vecLow[j]) {
i--;
j--;
}
if (i > j) { // low和high位数不同时
bool allLeftIsK_1 = false;
if (vecHigh[i] == k-1) {
allLeftIsK_1 = true;
for (int l = i; l >= 0; l--) {
if (vecHigh[l] != k-1) {
allLeftIsK_1 = false;
break;
}
}
}
if (allLeftIsK_1) //123 999999 -> 999999 high 所有位上都是k-1, ans = high
vecAns = vecHigh;
else { //123 123456 -> 099999 最高位置0,其他位置k-1
vecAns = vecHigh;
vecAns[i] = 0; // 最高位置0
i--;
while (i >= 0) {
vecAns[i--] = k-1;
}
}
}
else { // low 和 high位数相同时
bool allLeftIsK_1 = false;
if (vecHigh[j] == k-1) {
allLeftIsK_1 = true;
for (int l = j; l >= 0; l--) {
if (vecHigh[l] != k-1) {
allLeftIsK_1 = false;
break;
}
}
}
if (allLeftIsK_1) // 123456 123999 -> 123999 high 与low的不同位上都是k-1, ans = high
vecAns = vecHigh;
else { // 123456 123567 -> 123499 low 从不同位的下一位开始置k-1
vecAns = vecLow;
j--; // 从不同位的下一位置k-1
while (j >= 0) {
vecAns[j--] = k-1;
}
}
}
long ans = 0;
long power = 1;
for (int i = 0; i < vecAns.size(); i++) {
ans += power * vecAns[i];
power *= k;
}
return ans;
}
int main() {
int q;
cin >> q;
long low, high, ans;
int k;
for (int i = 0; i < q; i++) {
cin >> k >> low >> high;
ans = query(low, high, k);
cout << ans << endl;
}
return 0;
}
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scn=new Scanner(System.in);
while(scn.hasNextInt()){
int q=scn.nextInt();
for(int t=0;t<q;t++){
int k=scn.nextInt();
long l=scn.nextLong();
long r=scn.nextLong();
long d=r-l;
long temp=r;
int b=1;
while((temp/=k)!=0) b++;
if(Math.pow(k,b)-1==r) System.out.println(r);
else if(Math.pow(k,b-1)>l) System.out.println((long)Math.pow(k,b-1)-1);
else{
temp=l;
long[] a=new long[b];
for(int j=0;j<b;j++){
a[j]=temp%k;
temp/=k;
}
for(int j=0;j<b;j++){
d-=(k-1-a[j])*(long)Math.pow(k,j);
if(d<=0) System.out.println(l);
if(d<=0) break;
l=r-d;
}
}
}
break;
}
}
} 反复考虑过代码应该没问题,pow函数的浮点不确定性也测试过没有影响,但是通过率只有20%(没有超时或内存不足的问题,就是没通过),求教问题出在哪import java.util.ArrayList;
import java.util.Scanner;
/*
* 低位变 k-1 时,巧妙做法:假如百位数是5(八进制),
* 那么变成七(八进制数百位)要加 2,对应十进制数要加 2*(8^2)
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 0; i < n; i++) {
int k = sc.nextInt();
long l = sc.nextLong();
long r = sc.nextLong();
System.out.println(count(k, l, r));
}
}
public static long count(int k, long l, long r) {
// int num = 0;
// String str_l = invert(l, k);
// String str_r = invert(r, k);
ArrayList<Long> start = invert(l,k);
long sum = 1;
for(int i = 0;i < start.size();i++){
long ii = k - 1 - start.get(i);
if(l + ii * sum <= r){
l = l + ii * sum;
}else{
return l;
}
sum *= k;
}
// 当l所有k进制数位全变成k-1时,仍不超过r时
while(l < r){
// long iii = k * sum;
long iii = (k - 1) * sum;
if(l + iii <= r){
l += iii;
}else{
return l;
}
sum *=k;
}
// for(int i = 0;i < )
return l;
}
// public static String invert(long x,int k){
// LinkedList<Long> ll = new LinkedList<>();
// long r = 0;
// while(x > 0){
// r = x % k;
// ll.addFirst(r);
// x /= k;
// }
// StringBuffer sb = new StringBuffer();
// for(int i = 0;i < ll.size();i++){
// sb.append(ll.get(i));
// }
// return sb.toString();
// }
public static ArrayList<Long> invert(long x, int k) {
ArrayList<Long> arr = new ArrayList<>();
long r = 0;
while(x > 0){
r = x % k;
arr.add(r);
x /= k;
}
return arr;
}
}
q = int(input()) from collections import deque from math import pow def ToK(num,k): res = deque() while num: res.appendleft(num%k) num //= k return list(res) def Tonum(res,k): ans = 0 temp = 1 for i in range(len(res)-1,-1,-1): ans += res[i] *temp temp *= k return ans #ans = 0 #temp = 0 #for i in reversed(range(len(res))): # ans += res[i] * pow(k,temp) # temp += 1 #return int(ans) for i in range(q): k, l, r = tuple(map(int, input().split())) record, tmp = 0, 0 while tmp <= r: record = tmp tmp = tmp * k + (k - 1) if record >= l: print(record) else: low_k = ToK(l,k) for i in reversed(range(len(low_k))): if low_k[i] == k-1: continue else: change = low_k[i] low_k[i] = k-1 if Tonum(low_k[:],k) > r: low_k[i] = change break print(Tonum(low_k[:],k))
import math q = int(input()) def func(k, l, r): if l == r: return l if l == 0: return l order = math.ceil(math.log(l, k)) flag =False # k=10为例:寻找 [l,r] 内是否有 99,999,9999... 如果有,就输出最长的 9999。 for i in range(order, math.ceil(math.log(r, k)) + 1): mid = k ** i - 1 if mid <= r and mid >= l: min_res = mid flag = True if flag: return min_res # 上一部如果没找到连续的 9 组成的数,那就不看最高位,只看后面几位,如此递归下去: # k=10: 【3333,5678】-> 3000 +【333,2678】-> 3000 + 999 = 3999 else: left_ = k ** (order - 1) left = left_ * int(l / left_) min_res = left + func(k, l - left, r - left) return int(min_res) for i in range(q): k, l, r = [int(x) for x in input().split()] print(func(k, l, r)) 不需要很复杂吧,还差一步递归最后终止的判断,否则特殊情况死循环
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
/**
* @author YHX
* @date 2019/8/4 17:25
* description
*/
class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
/**
* call thReader method to initialize reader for InputStream
*/
static void init(InputStream input) {
reader = new BufferedReader(
new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}
/**
* get next word
*/
static String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
//TODO add check for eof if necessary
tokenizer = new StringTokenizer(
reader.readLine());
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
static long nextLong() throws IOException {
return Long.parseLong(next());
}
static double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
public class Main {
public static void main(String[] args) throws Exception {
Reader.init(System.in);
int n = Reader.nextInt();
while (n-- != 0) {
int k = Reader.nextInt();
long l = Reader.nextLong();
long r = Reader.nextLong();
int[] llist = dec2K(l, k);
long temp = 0;
long[] longs = new long[1000];
int cnt = 0;
while (temp <= r) {
longs[cnt] = temp;
temp = temp * k + k - 1;
cnt++;
}
if (longs[cnt - 1] >= l) System.out.println(longs[cnt - 1]);
else {
for (int i = 0; i < llist.length; i++) {
int tm = llist[i];
llist[i] = k - 1;
long x = K2Dec(llist, k);
if (x > r) {
llist[i] = tm;
System.out.println(K2Dec(llist, k));
break;
}
}
// System.out.println(ans);
}
}
}
private static long K2Dec(int[] list, int k) {
long sum = 0;
for (int i = list.length - 1; i >= 0; i--) {
sum = sum * k + list[i];
}
return sum;
}
private static int[] dec2K(long m, int k) {
int cnt = 0;
long mm = m;
while (mm != 0) {
mm /= k;
cnt++;
}
int[] list = new int[cnt];
int j = 0;
while (m != 0) {
list[j++] = (int) (m % k);
m /= k;
}
// System.out.println(Arrays.toString(list));
return list;
}
}
/*
1000
11 995685164714609 995685164714759
12 2736421049381634 2736421049406512
14 9118803148252731 9118865035350336
2 1999825671666783 2000343892027004
14 7193328445426973 7193328445427058
11 7732658659093208 7732658659093623
9 1480868347971885 1480868506943790
14 3042539992504302 3042540322182591
8 1389231659305990 1399565743027217
14 2932108313570593 7566855981538408
12 7325933386074263 7325933386150179
15 1475130408804666 1475130408814717
4 8369091548439239 8369091832832186
2 584922365242306 584928003053033
11 7722607142326413 7793990995548130
4 6402524556803908 6495021063230295
3 3030210225507683 3030210225507723
13 9258166811155326 9258166811155824
15 9721331831836073 9721331831863924
6 2729140398142086 2729140398194424
13 8051442428579126 8051442520463831
10 7797474285534101 7797474382623448
11 8086464978132222 8086507915606045
6 9943020962485391 9943028723407452
15 5136403641668815 5137054586129716
11 5622258309274901 5622404426526100
8 1536295471800580 2248394876465846
*/
/*
15
4 8442097414683844 8442097414683844
3 3173466882309064 3173466882309073
4 8527527027194177 8527527027194276
4 2661113491247500 2661113491248499
16 4448712248766526 4448712248776525
13 2684426398058983 2684426398158982
14 6562761408288807 6562761409288806
4 2847109288743406 2847109298743405
12 3011167199031338 3011167299031337
7 8655416323525458 8655417323525457
13 177186968879953 177196968879952
2 4133390730537405 4133490730537404
13 4680075382111731 4681075382111730
11 5341708995347620 5351708995347619
8 114951857079067 214951857079066
*/
代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> rdec2k(long long dec, int k) {
vector<int> ans;
while (dec / k) {
ans.push_back(dec % k);
dec = dec / k;
}
ans.push_back(dec);
return ans;
}
void get_ans(vector<int> &vrans, vector<int> &vrl, vector<int> &vrr, int k) {
if (vrl.empty() || vrr.empty()) {
return;
}
if (vrl.size() < vrr.size()) {
vrans.assign(vrr.size() - 1, k - 1);
}
else { // vrl.size() < vrr.size()
if (vrr.back() > vrl.back()) {
vrans.assign(vrl.size() - 1, k - 1);
vrans.push_back(vrl.back());
//return;
}
else {// vrr.back() == vrl.back()
int tmp = vrl.back();
vrl.pop_back();
vrr.pop_back();
get_ans(vrans, vrl, vrr, k);
vrans.push_back(tmp);
}
}
}
long long k2dec(vector<int> vrans, int k) {
long long ans = 0;
long long tmp = 1;
for (int i = 0; i < vrans.size(); ++i) {
ans += vrans[i] * tmp;
tmp *= k;
}
return ans;
}
int main() {
int N;
while (cin >> N) {
while (N--) {
int k;
long long l, r;
cin >> k >> l >> r;
vector<int> vrl = rdec2k(l, k); // 逆序存放k进制的l
vector<int> vrr = rdec2k(r + 1, k); // 逆序存放k进制的r+1, 数可以取的范围是[l, r+1)
vector<int> vrans; // 逆序存放k进制的答案
get_ans(vrans, vrl, vrr, k);
cout << k2dec(vrans, k) << endl; // 将答案转化成10进制后输出
}
}
return 0;
}以上是代码