博客地址:wmathor
首先了解几个定理:
约数个数定理
对一个大于1的整数n,n可以分解质因数为∏ki=1paii=p1a1·p2a2···pkak
则n的正约数的个数就是f(n)=∏ki=1ai+1=(a1+1)(a2+1)···(ak+1),这个很好证明,因为pa11的约数有p01,p11,p21…pa11,共(a1+1)个,同理pakk的约数有(ak+1)个
约数定理
n的(a1+1)(a2+1)···(ak+1)个正约数的和为:
(p01+p11+…+pa11)(p02+p12+…pa22)…(p0k+p1k+…pakk)
举个例子,180=22\*32∗51
约数个数:(2+1)(2+1)(1+1)=18
约数和:(1+2+4)(1+3+9)(1+5)=546
回到题目
对于这题来说,根据约数定理就有AB的约数和为:
(1+p11+…+pBa11)(1+p12+…pBa22)…(1+p1k+…pBakk)
定义sum(n,k)
为p0+p1+…+pk,分成两部分的和变为(p0+…+pk2)+(pk2+1+…pk)
后面的多项式提取pk2+1,变成(p0+…+pk2)+pk2+1∗(p0+…pk2)
将两项合并(1+pk2+1)∗(p0+…+pk2),这个式子可以转化为(1+pk2)∗sum(p,k2)
import java.util.Scanner;
public class Main {
static int mod = 9901;
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int a = cin.nextInt();
int b = cin.nextInt();
int res = 1;
for (int i = 2; i <= a; i++) {
int s = 0;
while (a % i == 0) {
s++;
a /= i;
}
if (s > 0)
res = res * sum(i, s * b) % mod;
}
if (a == 0)
res = 0;
System.out.println(res);
}
static int sum(int p, int k) {
if (k == 0)
return 1;
if (k % 2 == 0)
return (p % mod * sum(p, k - 1) + 1) % mod;
return (1 + pow(p, k/2 + 1)) * sum(p, k >> 1) % mod;
}
private static int pow(int a, int k) {
a %= mod;
int res = 1;
while (k != 0) {
if ((k & 1) == 1)
res = res * a % mod;
a = a * a % mod;
k >>= 1;
}
return res;
}
}
题解有问题的
为啥提取p^(k/2+1)后最后一项是p^(k/2)啊,不应该是p^(k/2-1)吗
同问
同问,应该是p^(k/2-1),这里应该讨论奇偶了呀。
因为这里的k是奇数 举个例子就懂了
Orz
哇靠很妙,自己直接循环TLE了,如果你这个思路就可以logn了
%%%orz
分析的真棒!又是一道数学题,说难也不是很难,但是不了解约束和定理的话还是很难AC
求n的正约束个数的公式f(n)最好是用括号括起ai+1
sum(n,k)哪里应该讨论一下k的奇偶情况吧。否则直接看(p0+…+p(k/2))+p(k/2+1)∗(p0+…p(k/2))共有k/2+1+k/2+1项=k+2项,sum(p,k)总共只有0~k, k+1项。
赞哇
数列和递归那边似乎要讨论k的奇偶性吧
太赞了吧