題目
思路我覺得這道題非常難,一開始我完全找不到思路,只能盡量的騙分,後來問了別人才明白怎麼做。本題最核心的是兩個陣列,ret1和ret2。ret2[i]儲存的是從1到最大的i位數的子串的位數,做法是ret[i-1]+i位的所有數的位數,比如ret[2],即1-99的位數,就是1-9的位數(ret[i])加上10-99的位數,(99-9)*2([pow(10,i)-pow(10,i-1)]*i)。ret1[i]中儲存的的是從開始到i位數的最大數字開始出現時的位數,1-9為45,1-99為9045(方法是用等差數列求和的方式,這也是本題最核心的乙個演算法之一,另乙個是二分法)。方法不好說,舉個例子講一下9045是怎麼求的(即ret1[2]),先算上ret1[1],然後剩下的90×9(1-9九位數),然後乙個從10,1011,101112…,101112…99的等差數列求和即可。其他的實現我都給了詳細的注釋,就是乙個挺複雜的數學問題,但是易出錯。
**
#include
#include
#include
#include
#define inf 1e18
using
namespace std;
typedef
long
long ll;
ll ret1[10]
;
ll ret2[10]
;
ll ret
(ll t)
ll r2=0;
for(ll i =
1;i) r2+
=(t-
pow(
10,r1-1)
+1)*r1;
return r2;
}void
query()
}//我們以time為2為例,即從10-99
ll l =1;
ll r =
pow(
10,time)
-pow(10
, time-1)
;//10到99一共90個二位數
ll mid;
ll rt=
ret(
pow(
10, time -1)
);//1-10一共多少位
ll rnk=0;
//記錄mid=r+l/2的名次
//二分
while
(l <= r)
//可能在 mid-1,mid,mid+1組中
ll t1=
(mid-2)
*rt+
(mid-2)
*(mid-3)
*time/2;
//mid-1前面的位數
ll t2=
(mid-1)
*rt +
(mid-1)
*(mid-2)
*time/2;
//mid
ll t3= mid *rt +
(mid-1)
*mid*time/2;
//mid+1
if(k<=t2)
else
else
}for
(int j =
1; j <=
9; j++)}
ll m1=k/time;
//有幾個time位數
ll m2=k%time;
//k在time位數的第幾位
if(m2==0)
else}}
intmain()
ret1[0]
=0;for
(ll i =
1; i <=
8; i++
) ret1[9]
=inf;
query()
;return0;
}
C 咕咕東的奇妙序列
乙個序列 112123123412345123456 即第一部分包含1至1之間的所有數字,第二部分包含1至2之間的所有數字,第三部分包含1至3之間的所有數字,第i部分總是包含1至i之間的所有數字。求第k項數字是多少,注意第56項的數字為0.由分析可知 第一部分到第九部分相鄰部分的數字長度加一 第十部...
咕咕東的奇妙序列
題目 咕咕東的奇妙序列 題意 輸入 輸出 樣例 解題思路 這個題還是挺難的,主要是資料太大了,如果用字首和只能過前六個點,1e18不是鬧著玩的,陣列裝不下的 這裡說說我的思路 首先,我先搞個大小為8的陣列,存的是從1 10 i的數 如,陣列第乙個元素為 112123123412345 1234567...
咕咕東的奇妙序列 二分 數字模擬
poj 1019 number sequence 題目給出一種序列表示方式,可以表示為 1 12 123 1234 12345678910 序列不帶空格 也就是說序列可被分組,第 i 組包含的是1到 i 的所有數字。題目給出多個詢問要求每次得到序列中第 k 位的數字。注意 k 要能取到 10 18....