现在有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; }
以上是代码