Sumdiv POJ - 1845 (逆元/分治)
Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S modulo 9901 (the rest of the division of S by 9901).
Input
The only line contains the two natural numbers A and B, (0 <= A,B <= 50000000)separated by blanks.OutputThe only line of the output will contain S modulo 9901.
Sample Input
2 3
Sample Output
15
Hint 2^3 = 8.
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
题意:求AB的所有约数的和 % MOD (9901) 题意中有点问题,我们知道0是没有约数的,我觉得A、B应该都是>0的
思路:我们可以把A分解质因数(p1c1 * p2c2 * .... * pncn)B
约数和:(1 + p1 + p12 + ... + p1B*c1)* (1 + p2 + p22 + ... + p2B*c2)* .... * (1 + pn + pn2 + ... + pnB*cn) ( 排列组合问题)
这样我们可以看出这是多个等比数列乘积,可以用等比数列求和公式 (a1 *(1-qn))/(1-q),我们注意到这里有除法,但是同余模定理是对于加减乘的,那么我们可以利用费马小定理,
求出(1-q)的逆元,然后把除变成乘逆元
坑点:应为 9901 这个质数较小,很容易找到一个数x,(x-1)% MOD == 0 ,就说明这个数是没有逆元的(例217823),那么对于这种情况,我们不能用逆元算,你会发现这种情况下,
pn % MOD == 1 ((p-1)% MOD == 0)),这样(1 + pn + pn2 + ... + pnB*cn) == (1 % MOD + pn %MOD + pn2 %MOD + ... + pnB*cn %MOD) == B*cn+1
#include<iostream>
#include<cstdio>
#include<math.h>
using namespace std; const int maxn = 1e4;
const int mod = ;
int a,b;
int p[maxn];
int c[maxn];
int calc(int x)
{
int m= ;
int up = sqrt(x);
for(int i=;i<=up;i++)
{
if(x % i == )p[++m] = i,c[m] = ;
while(x % i == )x/= i,c[m]++;
}
if(x > )p[++m] = x,c[m] = ;
return m;
} typedef long long ll; ll qpow(ll a,ll b)
{
ll ans = ;
ll base = a;
while(b)
{
if(b&)ans = (ans * base)%mod;
base = (base * base)%mod;
b >>= ;
}
return ans;
}
int main()
{
scanf("%d%d",&a,&b);
int n = calc(a);
ll ans = ;
for(int i=;i<=n;i++)
{
if((-p[i])%mod == )
{
ans = (ans * (b * c[i]+ ))%mod;
continue;
}
ll Ni = qpow(-p[i],mod-);
ll tmp = -qpow(p[i],c[i]*b+);
ans = (ans * (tmp*Ni%mod+mod)%mod)%mod;
}
printf("%lld\n",ans);
}
还有一种写法,就是不用公式计算等比数列和,这样就避免了逆元的问题
sum(p,c) = (1 + p + p2 + ... + pk)
(1)c为奇数,sum(p,k)= sum(p,(k-1 )/2)*(1+p(k+1)/2)
sum(p,c) = (1 + p + p2 + ... + p(k-1)/2)+ (p(k+1)/2 + ... + pk) (c为奇数,加上0次幂,变成偶数,刚好可以分成两个等长的数列)
(2)c为偶数,sum(p,k)= sum(p,k/2-1)*(1+pk/2)+ pk
sum(p,c) = (1 + p + p2 + ... + pk/2-1)+ (pk/2 + ... + pk-1)+ pk (c+1是奇数)
#include<iostream>
#include<cstdio>
#include<math.h>
using namespace std; const int maxn = 1e4;
const int mod = ;
int a,b;
int p[maxn];
int c[maxn];
int calc(int x)
{
int m= ;
for(int i=;i*i<=x;i++)
{
if(x % i == )p[++m] = i,c[m] = ;
while(x % i == )x/= i,c[m]++;
}
if(x > )p[++m] = x,c[m] = ;
return m;
} typedef long long ll;
ll qpow(ll a,ll b)
{
ll ans = ;
ll base = a;
while(b)
{
if(b&)ans = (ans * base)%mod;
base = (base * base)%mod;
b >>= ;
}
return ans;
}
ll sum(ll p,ll c)
{
if(c == )return ;
if(c&)return ((+qpow(p,(c+)/))%mod*(sum(p,(c-)/)%mod))%mod;
else return ((+qpow(p,c/))%mod*(sum(p,c/-))%mod+qpow(p,c))%mod;
} int main()
{
scanf("%d%d",&a,&b);
int n = calc(a);
ll ans = ;
for(int i=;i<=n;i++)
{
ans = (ans * sum(p[i],c[i]*b))%mod;
}
printf("%lld\n",ans);
}
Sumdiv POJ - 1845 (逆元/分治)的更多相关文章
- Sumdiv POJ 1845
http://poj.org/problem?id=1845 题目 Time Limit: 1000MS Memory Limit: 30000K Description Consider two ...
- 洛谷 P1593 因子和 || Sumdiv POJ - 1845
以下弃用 这是一道一样的题(poj1845)的数据 没错,所有宣称直接用逆元/快速幂+费马小定理可做的,都会被hack掉(包括大量题解及AC代码) 什么原因呢?只是因为此题的模数太小了...虽然990 ...
- poj 1845 POJ 1845 Sumdiv 数学模板
筛选法+求一个整数的分解+快速模幂运算+递归求计算1+p+p^2+````+p^nPOJ 1845 Sumdiv求A^B的所有约数之和%9901 */#include<stdio.h>#i ...
- 【POJ 1845】 Sumdiv (整数唯分+约数和公式+二分等比数列前n项和+同余)
[POJ 1845] Sumdiv 用的东西挺全 最主要通过这个题学了约数和公式跟二分求等比数列前n项和 另一种小优化的整数拆分 整数的唯一分解定理: 随意正整数都有且仅仅有一种方式写出其素因子的乘 ...
- poj 1845 【数论:逆元,二分(乘法),拓展欧几里得,费马小定理】
POJ 1845 题意不说了,网上一大堆.此题做了一天,必须要整理一下了. 刚开始用费马小定理做,WA.(poj敢说我代码WA???)(以下代码其实都不严谨,按照数据要求A是可以等于0的,那么结果自然 ...
- POJ1845 Sumdiv [数论,逆元]
题目传送门 Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 26041 Accepted: 6430 Des ...
- POJ 1845 Sumdiv 【二分 || 逆元】
任意门:http://poj.org/problem?id=1845. Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions ...
- poj 1845 Sumdiv (等比求和+逆元)
题目链接:http://poj.org/problem?id=1845 题目大意:给出两个自然数a,b,求a^b的所有自然数因子的和模上9901 (0 <= a,b <= 50000000 ...
- POJ 1845 Sumdiv 【逆元】
题意:求A^B的所有因子之和 很容易知道,先把分解得到,那么得到,那么 的所有因子和的表达式如下 第一种做法是分治求等比数列的和 用递归二分求等比数列1+pi+pi^2+pi^3+...+pi^n: ...
随机推荐
- 体验go语言的风骚式编程
最近想搞搞后台开发,话说注意力就转移到了公司用的golang.用Go做微服务比较方便,或许是因为golang强悍的语法吧,看到go的语法,自己已被深深的吸引.关于学习后台如何选择可以参考<做后台 ...
- (转)scikit-learn主要模块和基本使用方法
从网上看到一篇总结的很不错的sklearn使用文档,备份勿忘. 引言 对于一些开始搞机器学习算法有害怕下手的小朋友,该如何快速入门,这让人挺挣扎的.在从事数据科学的人中,最常用的工具就是R和Pytho ...
- Confluence 6 从外部小工具中注册访问
希望从 Confluence 中删除一个小工具,你可以选择小工具边上的 URL ,然后单击删除(Delete). 如果你希望取消订阅一个应用的小工具,你需要删除整个订阅.你不能仅仅删除你订阅中的某一个 ...
- linux 下创建共享文件夹
首先需要在win下共享一个盘 然后设置virtulbox 然后修改一串代码 参考原文 https://jingyan.baidu.com/article/2fb0ba40541a5900f2ec5f0 ...
- java多线程快速入门(十七)
多线程通讯实例(必须要有多个线程.必须要管理同一个变量:线程A生产一个变量,线程B消费一个变量) package com.cppdy; class User { public String usern ...
- LeetCode(71):简化路径
Medium! 题目描述: 给定一个文档 (Unix-style) 的完全路径,请进行路径简化. 例如,path = "/home/", => "/home&quo ...
- 《剑指offer》 二叉树的镜像
本题来自<剑指offer>二叉树的镜像 题目: 操作给定的二叉树,将其变换为源二叉树的镜像. 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 ...
- JS实现简单的观察者模式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Python模块的导入以及软件开发规范
Python文件的两种用途 1 . 当脚本直接使用,直接当脚本运行调用即可 def func(): print("from func1") func() 2 . 当做模块被导入使用 ...
- Caffe使用新版本CUDA和CuDNN
因为一些原因还是需要使用别人基于Caffe的代码,但是代码比较老,默认不支持高版本的cuda或者cudnn 怎么办呢?基本上就是把最新官方Caffe-BVLC的几个关键文件拿过来替换即可. 脚本如下: ...