题目描述
假设现在有两个自然数A和B,S是AB的所有约数之和。
请你求出S mod 9901的值是多少。
输入格式
在一行中输入用空格隔开的两个整数A和B。
输出格式
输出一个整数,代表S mod 9901的值。
数据范围
0≤A,B≤5×107
输入样例:
2 3
输出样例:
15
注意: A和B不会同时为0。
感谢@hkr04大佬指出本题目代码效率有点低,导致TLE.
现在已经加入剪枝优化AC了,大家可以放心食用.
正解
(数学(质因数分解,唯一分解定律,约数和公式),分治递归)
数学类分析
- 质因数分解,就是将一个数分解成为 p1c1×p2c2×…×pncn 比如说24=23×31
- 唯一分解定律,就是字面意思
- 约数和公式,如下文所示
AB=(1\+p11\+p12\+.....\+p1B\*c1)×(1\+p22\+.....\+pnB×c2)
sum(p,c)=1\+p\+p2\+…\+pc
然后呢我们可以通过分类以及乘法中的提取公因式法,将sum函数中c为奇数的公式和sum函数中c为偶数的公式推出。具体参考《算法竞赛进阶指南》,亦可以看我的cpp代码中的sum函数。
C++ 代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define Mod 9901
int a,b;
int ksm(int a,int b)//快速幂函数
{
int ans=1;
a%=Mod;
while(b)
{
if (b&1)
ans=ans%Mod*a;
a=a%Mod*a%Mod;
b>>=1;
}
return ans;
}
long long sum(int p,int c)
{
if (c==0)
return 1;
if(c&1)
return ((1+ksm(p,(c+1)>>1))*sum(p,(c-1)>>1))%Mod;//奇数的情况下
else
return ((1+ksm(p,c>>1))*sum(p,(c>>1)-1)+ksm(p,c))%Mod;//偶数的情况下
}
int main()
{
cin>>a>>b;
int ans=1;
for (int i=2;i<=a;i++)
{
int s=0;
while(a%i==0)
{
s++;
a/=i;
}
if (s)//这句话剪枝.然后就TLE变成了AC.by POJ
ans=ans*sum(i,s*b)%Mod;
}
if (a==0)
cout<<0<<endl;//特判的情况,这里非常的阴毒,出题人用心险恶
else
cout<<ans<<endl;
return 0;
}
约数和公式似乎是
S=(1+p11+p12+⋯+p1B∗c1)×(1+p22+⋯+p2B×c2)×⋯×(1+pn1+pn2+⋯+pnB∗cn)
大佬们能帮忙解答吗 https://www.acwing.com/video/116/

print("牛逼")
大佬,还是你的代码适合我
hhhhh好搞笑最后一句注释
Orz
%%%%Orz
/WoW/
∏ni=1∑B×cik=0pkiS=∏i=1n∑k=0B×cipik
唯一分解,不是要求乘子是质因数吗,当i为4时 ,乘子不就不是质数了吗?
2是质数哦
一开始我也想到这个问题,但实际上i从小到大,当i为4时,已经被i = 2整除完了,就不可能再被4整除了
nb!!!
QwQ
为什么是AB=∏ni=1∑B×cik=0pki
不应该是S=∏ni=1∑B×cik=0pki,S为约数和
吗?
这里有解释,太旧了,我有点忘记这道题目的思路了
话说唯一分解好像可以写成√(n)的吧
为什么不直接用求和公式加上求逆元
我是按照yxc老师的方法做的.
因为公式是(p^(n + 1) - 1)/(p - 1)
又因为要模9901所以在有一个点时,p^(n + 1) % 9901 = 1, 再减1是0,就错了
这个点是59407 3
交到poj上会t掉
能不能把POJ这道题目的网址发我一下,我去康康,有什么区别.按理说我这道题目代码不会TLE.
http://poj.org/problem?id=1845
感谢已经修改完毕.
请问
if(c&1) 不就直接判断为奇数吗
是的啊,这样写速度快
为什么偶数要加+ksm(p,c)
次数是奇数但是数因为还有个零次幂的关系会是偶数个数,所以后面要加一下
用等比数列求和公式+对分母求逆元应该更快,二分求和为logn*logn,快速幂求逆元为logn
ORZ
zbnb
’‘’
return ((1+ksm(p,(c+1)>>1))sum(p,(c-1)>>1))%Mod;//奇数的情况下
else
return ((1+ksm(p,c>>1))sum(p,(c>>1)-1)+ksm(p,c))%Mod;//偶数的情况下
‘’‘
在递归的过程中取模了无数次,但是按题目是smod9901,只取模了一次,为什么递归过程得到的结果是正确的?
这是可以的,因为取模运算是传递的啊.
而且你过程中如果不取模,那么你就会WA,除非你是高精度.
比如说,a%9901b和ab%9901是一样的
吼的,谢谢(ง •_•)ง