【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 ...