Wek8 CS-3

在这里插入图片描述
在这里插入图片描述
解题思路:

首先要找这个序列的规律,从整体来看,规律就是每次都是1到i,i++,观察可以对i进行划分,由i的位数对序列进行划分,称之为大组,比如i为1位数就在一大组,i为2位数就在二大组,具体到i就是小组,比如定位i为12,在二大组的第三小组,可以知道,大组的小组间包含的位数构成等差数列,如i=10,1到10就是11位数,i=11,只是增加了一个两位数(这是二大组的共性),位数为13。我是先通过等差数列和的运算存储每个大组的边界,这样就可以对输入的数进行判断属于哪个大组,再在组内进行二分搜索,判断在哪个小组,最后在该组进行搜索定位到具体的i即可,注意,输入的查询数q在此期间要一直更新,即相对与已知位置的偏移量,这样,定位到i就能查找到具体的某一位是什么了。
**>总结:这里出过很多错误,但是不大记得错误是什么了,emm,注意一下浮点精度这里的问题叭。

实验代码:

#include<iostream>
#include<cstdio>
#include<math.h>

using namespace std;
typedef unsigned long long ull;
long long int a[30];            
long long int a1[30];            
int tot;

void getAll() {
    a1[1] = 1;            
    ull n = 9;
    int i = 1;
    for (; a[i - 1] < 1e18; i++) {
        a[i] = a[i - 1] + a1[i] * n + (n * (n - 1)) / 2 * i;
        a1[i + 1] = a1[i] + (n - 1) * i + i + 1;      
        n *= 10;
    }
    tot = i - 1;            
    for (int i = 1; i <= tot; i++)
        cout << a1[i] << endl;
    for (int i = 1; i <= tot; i++)
        cout << a[i] << endl;
}

int cute(int num, int ans) {
    int temp = num;
    while (ans < 0) {
        temp /= 10;
        ans++;
        if (ans == 0)
            break;
    }
    return temp % 10;
}

ull get_num(ull a1, ull d, ull ans) {
    ull l = 0, r = 9*pow(10,d-1);	
    while (l < r) {
        ull mid = (l + r) >> 1;
        if (mid * a1 + mid * (mid - 1) / 2 * d >= ans)r = mid;
        else l = mid + 1;	 
    }
    return l-1;			
}
void getAns(ull k) {
    int d;
    for (int i = 1; i <= tot; i++) {
        if (k <= a[i]) {
            d = i;            
            break;            
        }
    }
    long long int ans = k - a[d - 1];
    ull a0 = a1[d];
    ull n = get_num(a0, d, ans);
    ans = ans - (n * a0 + n * (n - 1) * d / 2);
    ull temp = pow(10, d - 1) - 1 + n;         
    int tmp=0;
    ull t = 9;
    int j = 1;
    for (; j <= d; j++) {
        ans -= j * t;
        if (ans <= 0) {
            ans += j * t;    
            break;
        }
        tmp+=t;
        t *= 10;            
    }
    int mo = ceil((long double)ans / j);        
    tmp+=mo;
    ans = ans - mo*j;        
    cout << cute(tmp, ans);
}

int main(void) {
    getAll();
    int n;
    ull k;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        cin >> k;
        getAns(k);

    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值