二解 约数和luogu2715
来源:互联网 发布:linux 解压war 编辑:程序博客网 时间:2024/05/18 02:40
问题描述:给出a和b求a^b的约数和。
输入输出格式
输入格式:一行两个数a,b。
输出格式:一个数表示结果对 9901 的模。
输入输出样例
输入样例#1:2 3
输出样例#1:15
说明:对于 30%的数据,a,b≤ 10 对于 100%的数据,0 ≤ a,b ≤ 50 000 000
分析:此题题面简洁,容易想到,要求约数和,则可以利用约数和公式来暴力解,但是数据规模却明显的告诉你会TLE.那么会超时的地方在哪呢,分析下此题的做题步骤:
方法一:递归求等比数列之和
1.将a分解质因数,a=(p1^k1)(p2^k2)(p3^k3)….(pn^kn)
2.将每个质因数的指数 * b ,a^b =(p1^(k1 * b))(p2^(k2 * b))(p3^(k3 * b))….(pn^(kn * b))
3.根据约数和公式:对于已经分解的整数
有a^b的所有因子之和为
S = (1+p1+p1^2+p1^3+…p1^(k1* b)) * (1+p2+p2^2+p2^3+….p2^(k2 * b)) * (1+p3+ p3^2+…+ p3^(k3 * b)) * …. * (1+pn+pn^2+pn^3+…pn^(kn * b))
从上面步骤上来看,可知如果TLE,那一定是在第3步求因子之和上,亲测如果用快速幂并累加和累乘后在luogu上能40分,那么我们仔细观察因子之和的每个乘积因子都是一个等比数列之和,可以利用等比数列公式去计算,但是除法取余需要涉及到逆元【见方法二】,可以利用下图所示的公式递归得出:(此图感谢洛谷用户-恶魔)
证明如下图:
写到这,说明上面我虽列出3个操作步骤,实际上可以边质因数分解,边把2,3步逐步完成。
代码附上:
#include<iostream>#include<cmath>#define MOD 9901 using namespace std;int a,b,sum;int quickMod(int x,int y){//快速幂 int ans=1; x %= MOD; while(y){ if(y&1) ans = (ans * x) % MOD; y = y/2; x = (x * x)%MOD; } return ans;} int calc(int p,int c) //利用奇偶性递归求等比数列求和{ if(c == 0) return 1; if(c&1) return ((quickMod(p,(c+1)/2) + 1)%MOD * calc(p,(c-1)/2) % MOD)% MOD; else return (((quickMod(p,c/2) + 1) %MOD * calc(p,c/2 - 1)%MOD )%MOD + quickMod(p,c))%MOD;} int solve(){ int ans = 1,cnt; //质因数分解 for(int i = 2,t = sqrt(a); i<= t; i++) { if(a%i==0) { cnt = 0; //统计i的指数 while(a%i==0){ ++cnt; a = a/i; } int q = cnt * b; sum = calc(i,q); ans = (ans * sum)%MOD; } } if(a >1){ cnt = 1; int q = cnt * b; sum = calc(a,q); ans = (ans * sum)%MOD; } return ans; } int main(){ scanf("%d%d",&a,&b); printf("%d",solve()); return 0; }
方法二:逆元求等比数列求和,其他不变
#include<iostream>#include<cstdio>#include<cmath>#define MOD 9901 using namespace std;int a,b,sum;const int MD = 9901;typedef long long LL;LL exgcd(LL a,LL b,LL &x,LL &y) //扩展欧几里得{ if(b==0){ x = 1;y =0; return a; } else{ LL d = exgcd(b,a%b,x,y); LL t = x; x = y; y = t - a/b * y; return d; }}LL inv(LL b,LL n){ //求逆元 LL x,y; LL d = exgcd(b,n,x,y); if(d==1) return (x%n + n)%n; else return -1;}int quickMod(int x,int y){//快速幂 int ans=1; x %= MOD; while(y){ if(y&1) ans = (ans * x) % MOD; y = y/2; x = (x * x)%MOD; } return ans;} int solve(){ int ans = 1,cnt; //质因数分解 for(int i = 2,t = sqrt(a); i<= t; i++) { if(a%i==0) { cnt = 0; //统计i的指数 while(a%i==0){ ++cnt; a = a/i; } int q = cnt * b; int q_1 = inv(i-1,MOD) ; //求i-1的逆元 sum=((quickMod(i,q+1) - 1) * q_1)%MOD; //按等比数列求和公式计算和值 ans = (ans * sum)%MOD; } } if(a >1){ cnt = 1; int q = cnt * b; LL q_1 = inv(a-1,MOD) ; //求a-1的逆元 sum=((quickMod(a,q+1) - 1) * q_1)%MOD; //按等比数列求和公式计算和值 ans = (ans * sum)%MOD; } return ans; } int main(){ scanf("%d%d",&a,&b); printf("%d",solve()); return 0; }
- 二解 约数和luogu2715
- 约数个数及约数和
- 约数个数定理 和 约数和定理
- 约数个数定理and约数和定理
- 线性筛 [约数个数/约数和]
- wikioi 1396 约数和
- POJ 1845 约数和
- poj1845Sumdiv+约数和定理
- 洛谷 P2424 约数和
- n的约数和
- [bzoj3994]约数个数和
- uva11728-约数的和
- 最大约数和
- 约数和定理
- 洛谷 P2424 约数和
- P2424 约数和
- 整数的约数和
- [杜教筛 约数和前缀和] 51Nod 1220 约数之和
- 排序五:冒泡排序
- 第十二天总结
- BZOJ 2005 能量采集(莫比乌斯反演+分块)
- Android如何自定义Preference呢?
- python 写excel(2)
- 二解 约数和luogu2715
- 大数据特征与作用
- Python-栈的链式表实现(没写清楚)
- zxing生成二维码图片
- 复习一下java的反射
- platform下的按键驱动
- LeetCode 198. House Robber
- QAQ & ORZ 的签到题
- 暑假第11天总结