poj 1019 number sequence
題目給出一種序列表示方式,可以表示為 1 12 123 1234 … 12345678910 …(序列不帶空格)。也就是說序列可被分組,第 i 組包含的是1到 i 的所有數字。題目給出多個詢問要求每次得到序列中第 k 位的數字。注意 k 要能取到 10^18.
首先說明題目序列的含義和詢問方式,k的最大取值就是序列的最長長度,並且本題中要按照 k 位來查詢,這就使得序列中兩位以上的數字很難處理,也就是要將序列分為若干個大組,每個大組包含多個小組。大組可以按照1~9,10~99,100~999,…這樣的方法來分,因為每一小組內最大數字的位數相同,同時這樣分組可以降低之後定位是的時間複雜度,這一點對於10^18的資料量非常關鍵。
分好組後,我們需要得到每一大組及其之前大組所包含的元素總和,以便定位 k 所在的大組,這一點可以用等差數列的求和思路來做。同時我們還要能確定每一大組的小組內,不同位數數字的分界點,以便找到 k 對應的位置所對應數字的位數,方便從這個數字中取一位(思路複雜,反覆琢磨)。需要用到二分查詢的地方就是要去除 k 對應大組內所有在 k 對應小組之前的小組的元素數。之後由上面說過的方法,再去除 k 對應小組內所有位數小於 k 對應數字位數的元素和,這樣 k 表示的值就是 k 對應數字的從左往右第 k 位。之後只要找到這一位就可以了,注意細心。
本題在csp模擬時的資料量十分龐大,要遠大於poj上的情況,因此poj上的題解是不能直接使用的。據我觀察,poj上的大多題解是直接按照小組來存貯組內元素個數,然後尋找 k 對應的小組,這樣自然是比直接暴力尋找快一些,但還是達不到本次題目要求,所以必須要採用兩次分組。但是兩次分組更加繁瑣易錯,一定要十分細緻準確理解陣列的含義和上述確定數字的方法。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define maxn 10005
#define inf 1e9
using
namespace std;
ll q,l,r,k,t,mid,l,r,cnt;
ll a[maxn]
,b[maxn]
,c[maxn]
,d[maxn]
;voidin(
long
long
&x)while
(c<=
'9'&&c>=
'0')
x*=y;}
void
out(
long
long x)
if(x>9)
out(x/10)
;putchar
(x%10
+'0');
}void
init()
k =9;
for(ll i =
1; i <=9;
++i)
k =9;
for(ll i =
1; i <=9;
++i)
}bool
check
(ll x)
//確定x是否是k之前包含的該大段內的組數
ll sum
(ll x)
//減去k之前包含的該大段內的組數的總元素數
void
sol(ll x)
//將連續數字分解
d[++cnt]
= x %10;
}int
main()
} k -
= a[t-1]
; l =
1; r =
1e9;
while
(l < r)
k -=sum
(l-1);
for(ll i =
1; i <=9;
++i)
} k -
= b[t-1]
; l = k / t;
r = k % t;
//位數相同的第l個數字倒數第r位
if(r ==0)
else
}return0;
}
咕咕東的奇妙序列
題目 咕咕東的奇妙序列 題意 輸入 輸出 樣例 解題思路 這個題還是挺難的,主要是資料太大了,如果用字首和只能過前六個點,1e18不是鬧著玩的,陣列裝不下的 這裡說說我的思路 首先,我先搞個大小為8的陣列,存的是從1 10 i的數 如,陣列第乙個元素為 112123123412345 1234567...
C 咕咕東的奇妙序列
乙個序列 112123123412345123456 即第一部分包含1至1之間的所有數字,第二部分包含1至2之間的所有數字,第三部分包含1至3之間的所有數字,第i部分總是包含1至i之間的所有數字。求第k項數字是多少,注意第56項的數字為0.由分析可知 第一部分到第九部分相鄰部分的數字長度加一 第十部...
M2 C 咕咕東的奇妙序列
題目 思路我覺得這道題非常難,一開始我完全找不到思路,只能盡量的騙分,後來問了別人才明白怎麼做。本題最核心的是兩個陣列,ret1和ret2。ret2 i 儲存的是從1到最大的i位數的子串的位數,做法是ret i 1 i位的所有數的位數,比如ret 2 即1 99的位數,就是1 9的位數 ret i ...