POJ 1845 【Sumdiv】


【题目大意】

给定\(A\)和\(B\),求\(A^B\)的所有约数之和,对\(9901\)取模。
(对于全部数据,\(0<= A <= B <=50,000,000\))

【样例输入】

2 3

【样例输出】

15

【算法关键词】

  • 数论
  • 综合模板
  • 二分,乘法逆元

【题解】

不管什么题首先思考的肯定是暴力解法。起码可以骗分啊,当然,如果能一眼标算,那再好不过了。
这道题暴力做法就不说了,其实仔细思考也不会真的打暴力吧。。。

看见约数,首先想到的应该就是数论的有关知识。那么这道题实际上就是在求\(A^B\)的约数之和,问题的难点就在于求解答案的时间优化。

首先,可以思考唯一分解定理,即任意一个自然数都可分解且只能分解成以下形式:
\[ n=p_1^{k_1}*p_2^{k_2}*p_3^{k_3}*...*p_m^{k_m} \]

其中,\(p\)为质因数,\(k\)为自然数。

那如何实现呢?

首先通过线性筛把题目范围内的质数筛出来存在一个数组里,然后枚举数组里的质数是否能被\(A\)整除,即枚举\(p\),如果能,就以\(p\)为底枚举\(k\),并存入相对应的数组。

于是就可分解为:
\[ A^B=p_1^{k_1*B}*p_2^{k_2*B}*p_3^{k_3*B}*...*p_m^{k_m*B} \]

设\(a\)所有约数和为\(ans(a)\)
对于两个互质的数\(a\),\(b\),必定有\(ans(ab)=ans(a)*ans(b)\):

令\(a\)约数为\(x_1\),\(x_2\)...\(x_m\),\(b\)约数为\(y_1\),\(y_2\),...\(y_n\)
由\(a\),\(b\)互质,\(a_1->a_m\)与\(b_2->b_n\)无公共元素
那么
\[ ans(ab)=\sum_{i=1,j=1}^{i<=m,j<=n}x_i*y_j\\ \quad=\sum_{i=1}^{m}x_i*\sum_{j=1}^{n}y_j\\ =ans(a)*ans(b) \]
得证 这不是积性函数的性质吗

同理,\(p_i^{k_i*B}\)与\(p_j^{k_j*B}\)互质
所以:
\[ ans(A^B)=\prod_{i=1}^msum_i \]
其中:
\[ sum_i=\sum_{j=0}^{k_i*B}p_i^j \]
即:
\[ ans(A^B)=\prod_{i=1}^{m}\sum_{j=0}^{k_i*B}p_i^j \]
(理解不透彻的可以把这个拆开看看)

公式推到这里,其实就可以写代码了,在这里,还要注意\(sum_i\)的计算。

\[ sum_i=p_i^0+p_i^1+p_i^2+...+p_i^{k_i} \]

这里有两种方法。

  1. 二分+递归思想
    若\(k_i\)为奇数:
    \[ sum(p, k) = sum(p, k/2)*(1+p^{n/2+1}) \]
    若\(k_i\)为偶数:
    \[ sum(p, k) = sum(p, k/2-1)*(1+p^{n/2+1})+p^{n/2} \]
    证明的话可以把上面的式子拆开来看,这里不再赘述。

  2. 等比数列通项公式
    \[ sum(p, k) = \frac{p^{k+1}-1}{p-1} \]
    当然,如果在模的意义下这样做就需要乘法逆元的相关知识,这里就只给出法一的代码。法二的代码可以自己尝试下。其实是因为我懒
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>#define debug() puts("FBI WARNING!")
#define ll long long
#define R registerusing namespace std;/*常量申明*/
const int MAX = 500000;
const int BIG_SEVEN = 777777;
const int MEIZI = 100000;
const int mod = 9901;
/*函数申明*/
void ola(); void test(); void divide(); void cls();void solve();
ll binary_pow(ll, ll); ll sum(ll, ll); ll read();
/*变量申明*/
ll a, b, s, prim[BIG_SEVEN], p[MEIZI], k[MEIZI];
bool vis[MAX + 5];
int cnt, tot;int main(){ola();while (~scanf("%lld %lld", &a, &b)) {cls();divide();solve();//test();}return 0;
}inline ll read(){ // 快读 (貌似没用上) ll f = 1, x = 0;char ch;do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); return f*x;
}inline void ola() { // 欧拉筛 vis[1] = 1;for (R int i = 2;i < MAX; ++i) {if (!vis[i]) {prim[cnt++] = i;}   for (R int j = 0;j < cnt ; ++j) {if (i*prim[j] > MAX) break;vis[i*prim[j]] = 1;if (i%prim[j] == 0) break;}}
}inline void cls() {tot = 0, cnt = 0;} // 多组数据初始化  inline void divide() { // 唯一分解定理  memset(k, 0, sizeof(k));ll rose = a;for (R int i = 0; prim[i] <= rose/prim[i]; ++i) {if (rose%prim[i] == 0) {p[tot] = prim[i];while (rose%prim[i] == 0) {
//              debug();k[tot]++;rose /= prim[i];}tot++;}}if (rose != 1) {p[tot] = rose;k[tot++] = 1;}
}inline void solve() { // 累加答案 ll ans = 1;for (R int i = 0; i < tot; ++i) {ans *= (sum(p[i], b*k[i]) %mod);ans %= mod;}printf("%lld\n", ans);
}inline void test() { // 测试函数
/*check ola()*/for (R int i = 0;i < cnt; ++i) {cout << prim[i] << " ";}printf("%.2lf\n",(double)clock()/CLOCKS_PER_SEC);/*check divide()*/for (R int i = 0;i < tot; ++i) {printf("%lld^%lld\n", p[i], k[i]); }cout << tot;
}inline ll binary_pow(ll a, ll b) { // 二进制实现的快速模幂 ll ans = 1, tmp = a%mod;while (b) {if (b&1) {ans *= tmp; ans %= mod;}b >>= 1;tmp *= tmp; tmp %= mod;}return ans;
}inline ll sum(ll p, ll k) { // 约数和二分实现(p^0+p^1+...+p^k) if (p == 0) return 0;if (k == 0) return 1;if (k & 1) return ((1+binary_pow(p, k/2+1)) %mod * sum(p, k/2) %mod) %mod; // 奇数  else return ((1+binary_pow(p, k/2+1)) %mod*sum(p, k/2-1) + binary_pow(p, k/2) %mod) %mod;
}

三玖天下第一!

转载于:https://www.cnblogs.com/silentEAG/p/10385915.html

【简●解】POJ 1845 【Sumdiv】相关推荐

  1. c语言的幂乘积表达式,POJ 1845 Sumdiv [素数分解 快速幂取模 二分求和等比数列]

    大致题意: 求A^B的所有约数(即因子)之和,并对其取模 9901再输出. 解题基础: 1) 整数的唯一分解定理: 任意正整数都有且只有一种方式写出其素因子的乘积表达式. ,其中 为素数 2) 约数和 ...

  2. poj 1845 Sumdiv (算数基本定理+逆元)

    输入a和b,求a^b的所有因子之和. #include <iostream> #define ll long longusing namespace std;const int mod=9 ...

  3. POJ 1845 Sumdiv 【逆元】

    题意:求A^B的所有因子之和 很容易知道,先把分解得到,那么得到,那么 的所有因子和的表达式如下 第一种做法是分治求等比数列的和  用递归二分求等比数列1+pi+pi^2+pi^3+...+pi^n: ...

  4. Linux等比数列脚本求和,POJ 1845 (约数和+二分等比数列求和)

    题目大意:A^B的所有约数和,mod 9901. 解题思路: ①整数唯一分解定理: 一个整数A一定能被分成:A=(P1^K1)*(P2^K2)*(P3^K3).....*(Pn^Kn)的形式.其中Pn ...

  5. Sumdiv POJ - 1845

    Sumdiv POJ - 1845 题意: 求ABA^BAB的所有约数之和mod 9901(1<=A,B<=5e7) 题解: 我们先将A分解质因子,表示为:p1c1∗p2c2∗...... ...

  6. 【POJ 1845】 Sumdiv (整数唯分+约数和公式+二分等比数列前n项和+同余)

    [POJ 1845] Sumdiv 用的东西挺全 最主要通过这个题学了约数和公式跟二分求等比数列前n项和 另一种小优化的整数拆分  整数的唯一分解定理: 随意正整数都有且仅仅有一种方式写出其素因子的乘 ...

  7. 最新版freetextbox(版本3.1.6)在asp.net 2.0中使用简解

    最新版freetextbox(版本3.1.6)在asp.net 2.0中使用简解 2008-10-14 12:21 简介:对于FreeTextBox(版本3.1.6)在ASP.Net 2.0中使用,只 ...

  8. 最新版FreeTextBox(版本3.1.6)在ASP.Net 2.0中使用简解(提供博客园本地下载)

    来源:cleocn.com 最新版FreeTextBox(版本3.1.6)在ASP.Net 2.0中使用简解(提供博客园本地下载) 简介:对于FreeTextBox(版本3.1.6)在ASP.Net ...

  9. 爬虫5-BeautifulSoup模块简解2

    1.BeautifulSoup简解2 from bs4 import BeautifulSoup import re file = open("./baidu.html",'rb' ...

最新文章

  1. Linux系统中的Page cache和Buffer cache
  2. 已知bug列表——Solidity中文文档(12)
  3. 了解Java中的内存泄漏
  4. Windows与VMware下的Linux文件共享方式总结
  5. vue 表单验证按钮事件交由父组件触发
  6. 算法学习之路|最小生成树—kruskal
  7. 某云商城发卡网源码 带视频教程
  8. 中国烤箱盘行业市场供需与战略研究报告
  9. 机器学习基石笔记2——在何时可以使用机器学习(2)
  10. Android ScrollView 使用总结
  11. 【记录】搭建本地wordpress全过程
  12. 致远OA ajaxAction formulaManager 文件上传漏洞
  13. 阿里巴巴中国站搜索店铺列表 API 返回值说明
  14. 草莓网购物软件测试,网上商城系统的测试用例集
  15. 关于Tween的几个注意事项
  16. 5个最好的WordPress电子商务插件比较 - 2018年
  17. (Java实现) 光荣的梦想
  18. 2017ccps网络赛 1003 Friend-Graph(暴力)HDU 6152
  19. 动态规划解决0-1背包问题详解(图文并茂)
  20. dos攻击的工具——pentmenu

热门文章

  1. jpg怎么合成一份_海外商标注册申请程序复杂吗?应该怎么注册?
  2. python十大必备知识_学Python必备的基础知识
  3. setuptools清华源_setuptools与pip的依赖关系解决方案之间的差异
  4. python 血缘进程共享数据
  5. nginx ngx_http_core_module(http server location)
  6. 图解TCPIP-DHCP
  7. Centos 网络配置
  8. kafka jar包_Kafka系列文章之安装测试-第2篇
  9. 块存储性能--阿里云ECS磁盘
  10. 如何在VMware软件上安装Red hat(红帽)Linux6.9操作系统