HNOI2011 數學作業

2021-09-12 09:56:01 字數 1344 閱讀 5109

【hnoi2011】數學作業

小 c 數學成績優異,於是老師給小 c 留了一道非常難的數學作業題:

給定正整數 n 和 m ,要求計算concatenate(1..n) mod m 的值,其中 concatenate(1..n) 是將所有正整數 1,2,…,n順序連線起來得到的數。例如,n=13, concatenate(1..n)=12345678910111213 .小c 想了大半天終於意識到這是一道不可能手算出來的題目,於是他只好向你求助,希望你能編寫乙個程式幫他解決這個問題。

彩筆還是沒有思路啊~

其實本題用到的思路是,當你求乙個數對某乙個值取模的時候,可以按位取模,即從高位向低位求這個數的過程中不斷取模。可是這樣的話,複雜度就是o(n)了,n是1e18的,我勒個去。

嘿嘿,遞推過不去?上矩陣快速冪啊!不過這道題有點小麻煩,你列出式子,f【n】=f【n-1】*10^k+n,k是n的位數。矩陣加速遞推的時候,係數必須是固定不變的,現在這樣的話,我們無法進行遞推。所以需要對數進行分塊處理,每次處理相同位數的數,做一次矩陣快速冪。還有就是把n拆成n-1+1,這樣就和f【n-1】保持一致了。設計1*3的狀態矩陣與3*3的狀態轉移矩陣,做完快速冪之後f就是答案。

這道題比較神奇的是兩個數相乘之前一定取模,沒取模就奇怪的wa了。

#include#include

#include

#include

#define ll long long

using

namespace

std;

ll n,mod,t,a[

3][3],f[3][3

];void mul(ll a[3][3],ll b[3][3],ll c[3][3

]);

for(int i=0;i<3;++i)

for(int j=0;j<3;++j)

for(int k=0;k<3;++k)

tmp[i][j]=(tmp[i][j]+(a[i][k]%mod)*(b[k][j]%mod))%mod;

for(int i=0;i<3;++i)

for(int j=0;j<3;++j)

c[i][j]=tmp[i][j];

}void

calc(ll t,ll last)

}int

main()

else

calc(t,n);

}printf(

"%lld\n

",f[0][0

]);

return0;

}

2019-01-18 14:39

kgxpbqbyt 閱讀(

...)

編輯收藏

HNOI2011 數學作業

我又對著跑出正解的程式調了好久 怕不是眼瞎了 這就是個分段矩陣,我們很容易就得到了遞推式 f i f i 1 10 k i 其中 k log i 於是就是分段矩陣 矩陣 之後就是 了,沒有加快速乘wa了好久 cpp include include include define re register...

HNOI2011 數學作業

小 c 數學成績優異,於是老師給小 c 留了一道非常難的數學作業題 給定正整數 n 和 m,要求計算 concatenate 1 n mod m 的值,其中 concatenate 1 n 是將所有正整數 1,2,n 順序連線起來得到的數。例如,n 13,concatenate 1 n 123456...

HNOI2011 數學作業

時間限制 1 s 記憶體限制 128 mb solution 用矩陣乘。在向後插入數時,相當於把原答案乘10的多少次方再加上這個數,所以我們可以導成矩陣。a矩陣 b矩陣 ans 10 j 1 0 i 0 1 1 1 0 0 1 b矩陣第一行是把ans 10 j i,第二行是讓i加1,第三行是保持a ...