SRM394 Div2 1000
問題
0より大きい整数kは、mより小さく、mを割り切れるが、k^nではmを割り切れないとき、「mのcool divisor」という。d(m)は、整数mでのcool divisorの数とする。整数a,bについて、d(a)+d(a+1)+...+d(a+b)の値を返す。
1<=a<=10^6
1<=b<=10^7
2<=n<=10
考え方
総和について、視点を変えて、「x以下でkが約数の個数はx/k(=xをkで割った整数部分)」という事実を知っているかどうか。
(aからa+bまでの約数の個数)-(そのn乗での約数の個数)で計算できる。
■aからa+bまでの約数の個数
約数の個数を求めるために、「x以下でkが約数の個数は(x/k)」を用いて、
for(int k=2; k<=a+b; k++){ //k=1はそのn乗(==1)が割り切れるためcool divisorではない //(a+bまでの約数kの個数) - (a-1までの約数kの個数) == (aからa+bまでの約数kの個数) ret += ((a+b)/k) - ((a-1)/k); //k<mでなければならないので、 // kがa以上の時、k>=aのkの倍数の最後の値はcool divisorとしてありえない if(k>=a) ret--; }
■そのn乗での約数の個数
上と同じ方法で、約数の個数を計算する。
k^nが約数のaからa+bまでの個数を求めるので、実際にk^nを計算して( (a+b)/k^n )-( (a-1)/k^n )がn乗での約数の個数になる。
反省
手も足もでなかった。
素因数分解で約数の個数を求めるのではなく、「x以下でkが約数の個数はx/k」をk=2,...でループを回して計算できる。