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: ...
随机推荐
- Oracle 数据库导入与出
Oracle 数据库导入与出 导出( EXPORT )是用 EXP 将数据库部分或全对象的结构和导出 . 导入( 导入( IMPORT )是用 )是用 IMP IMP将 OS 文件中的对象结构和数据装 ...
- oracle_基本SQL语言
一:DDL数据定义语言 1:create(创建) 创建表 CREATE TABLE <table_name>( column1 DATATYPE [NOT NULL] [P ...
- Confluence 6 通过 SSL 或 HTTPS 运行 - 备注和问题解决
备注 在创建证书时候的背景信息: 'keytool -genkeypair' 命令将会创建秘钥对,包括公钥和关联的私钥,然后存储到 keystore 中.这个命令打包公钥为 X.509 v3 自签 ...
- SWift中 '?' must be followed by a call, member lookup, or subscript 错误解决方案
那是因为你在使用自己写的分类时没有指定返回的数据类型 指定下返回数据类型就好了 我是用的oc写的分类在Swift中使用的 错误代码 private lazy var btn = UIButton.C ...
- linux之xxx 不在 sudoers 文件中,此事将被报告(转载)
linux中创建用户命令为:useradd 用户名, eg: useradd test 指定密码:passwd test 但是有时候我们需要使用test运行执行一些root用户才有权限执行的命令,此时 ...
- nmap 扫描信息收集
1.端口镜像 port Mirroring 功能通过在交换机上或者路由器上,将一个或者多个源端口的数据流量妆发大奥某一个指定的端口来实现对网络的监听,指定端口成为镜像端口或目的端口. 2.ARP攻击捕 ...
- bzoj 3191
非常好的一道题 看到这道题,肯定能想到概率dp,但是状态的设计与转移都是一个难点 如果正向模拟来设计状态,那么不难发现是很难以转移的 所以我们考虑反向模拟,用类似博弈的方法来转移 不难发现,如果只剩了 ...
- Linux系统下inode满了导致无法写文件的解决思路
解决思路1:删除无用的临时文件,释放inode 进入/tmp目录,执行find -exec命令 find /tmp -type f -exec rm {} \; 遍历寻找0字节的文件,并 ...
- Gson将字符串转map时,int默认为double类型
gson能够将json字符串转换成map, 但是在转成map时, 会默认将字符串中的int , long型的数字, 转换成double类型 , 数字会多一个小数点 , 如 1 会转成 1.0 Gs ...
- Log4Net帮助类
工具类 using System; using System.Diagnostics; using log4net; namespace Trumgu_BI_PF.Util { public clas ...