题目大意就是给定a和b,求a^b的约数和

f(n) = sigma(d) [d|n]

这个学过莫比乌斯反演之后很容易看出这是一个积性函数

那么f(a*b) = f(a)*f(b)  (gcd(a,b)=1)

那么这道题就可以将a分解为每一个素数的k次方,求出相对应的f(p^k),将每一个乘在一起就行了

因为每一个素数得到的都是只有唯一的素数因子,那么f(n) 又变成了求 a^0+a^1+a^2....+a^k的值了 (n=a^k)

这里因为要取模,所以我用的是矩阵快速幂求的,网上别人用的都是二分分治求等比数列,反正这两种方法都不需要逆元,都能过

但我最开始写的要逆元的方法过不了也不知道为什么,希望路过大神知道的提个醒

矩阵快速幂的矩阵构造两维,第一维是等比关系,第二维保存前面所有值的和

{

a , a

0 , 1

}

分治求等比数列的和:

3: 用递归二分求等比数列1+pi+pi^2+pi^3+...+pi^n:

(1)若n为奇数,一共有偶数项,则:
      1 + p + p^2 + p^3 +...+ p^n

= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
      = (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))

上式红色加粗的前半部分恰好就是原式的一半,那么只需要不断递归二分求和就可以了,后半部分为幂次式,将在下面第4点讲述计算方法。

(2)若n为偶数,一共有奇数项,则:
      1 + p + p^2 + p^3 +...+ p^n

= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
      = (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);

上式红色加粗的前半部分恰好就是原式的一半,依然递归求解

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define ll long long
const int MOD = ; struct Matrix{
int m[][];
void init(){memset(m , , sizeof(m)); m[][] = m[][] = ;}
Matrix operator*(const Matrix &p)const {
Matrix ans ;
for(int i= ; i< ; i++)
for(int j= ; j< ; j++){
ans.m[i][j] = ;
for(int k= ; k< ; k++)
ans.m[i][j] = (ans.m[i][j]+m[i][k]*p.m[k][j]%MOD)%MOD;
}
return ans;
}
void out(){
cout<<m[][]<<" "<<m[][]<<endl<<m[][]<<" "<<m[][]<<endl;
}
}; Matrix q_pow(Matrix a , int b)
{
Matrix ans;
ans.init();
while(b){
if(b&) ans = ans*a;
a = a*a ; b>>=;
}
return ans;
} int get(int a , int b)
{
//a^0+a^1+a^2...+a^b
Matrix p;
p.m[][] = a%MOD , p.m[][] = a%MOD , p.m[][] = , p.m[][] = ;
p = q_pow(p , b);
return (p.m[][]+p.m[][])%MOD;
} void fenjie(int a , int b)
{
int mx = (int)sqrt(a+0.5) , ret = ;
for(int i= ; i<=mx ; i++){
if(i>a) break;
int cnt = ;
while(a%i==){
cnt+=b , a/=i;
}
if(cnt) ret = (ret*get(i , cnt))%MOD;
}
if(a>) ret = (ret*get(a , b))%MOD;
printf("%d\n" , ret);
} int main() {
// freopen("a.in" , "r" , stdin);
// freopen("compare.txt" , "w" , stdout);
int a , b;
while(~scanf("%d%d" , &a , &b)){
if(a == ) puts("");
else fenjie(a , b);
}
return ;
}

矩阵快速幂

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define ll long long
const int MOD = ; int q_pow(int a , int b)
{
a = a%MOD;
int ret = ;
while(b){
if(b&) ret = ret*a%MOD;
a = a*a%MOD ; b>>=;
}
return ret;
} int inv(int a){return q_pow(a , MOD-);} int sum(int a , int b)
{
//a^0+a^1+a^2...+a^b
if(b==) return ;
if(a==) return ;
if(b&) return ((+q_pow(a , b/+))%MOD*(sum(a , b/)%MOD))%MOD;
else return ((+q_pow(a , b/+))%MOD*(sum(a , b/-)%MOD)%MOD+(q_pow(a , b/)%MOD))%MOD;
} void fenjie(int a , int b)
{
int mx = (int)sqrt(a+0.5) , ret = ;
for(int i= ; i<=mx ; i++){
if(i>a) break;
int cnt = ;
while(a%i==){
cnt+=b , a/=i;
}
if(cnt) ret = (ret*sum(i , cnt))%MOD;
}
if(a>) ret = (ret*sum(a , b))%MOD;
printf("%d\n" , ret);
} int main() {
// freopen("a.in" , "r" , stdin);
// freopen("compare.txt" , "w" , stdout);
int a , b;
while(~scanf("%d%d" , &a , &b)){
if(a == ) puts("");
else fenjie(a , b);
}
return ;
}

分治

POJ 1845 求a^b的约数和的更多相关文章

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

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

  2. poj 1845 Sumdiv(约数和,乘法逆元)

    题目: 求AB的正约数之和. 输入: A,B(0<=A,B<=5*107) 输出: 一个整数,AB的正约数之和 mod 9901. 思路: 根据正整数唯一分解定理,若一个正整数表示为:A= ...

  3. poj 1845 POJ 1845 Sumdiv 数学模板

    筛选法+求一个整数的分解+快速模幂运算+递归求计算1+p+p^2+````+p^nPOJ 1845 Sumdiv求A^B的所有约数之和%9901 */#include<stdio.h>#i ...

  4. poj 1845 【数论:逆元,二分(乘法),拓展欧几里得,费马小定理】

    POJ 1845 题意不说了,网上一大堆.此题做了一天,必须要整理一下了. 刚开始用费马小定理做,WA.(poj敢说我代码WA???)(以下代码其实都不严谨,按照数据要求A是可以等于0的,那么结果自然 ...

  5. Java求555 555的约数中最大的三位数。

    package org.llh.test; /** * 求555 555的约数中最大的三位数 * @author llh * */ public class Car { //整数j除以整数i(i≠0) ...

  6. Sumdiv POJ - 1845 (逆元/分治)

    Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S m ...

  7. POJ 1845 Sumdiv (整数唯一分解定理)

    题目链接 Sumdiv Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 25841   Accepted: 6382 Desc ...

  8. POJ - 1845 简单数论

    求A^B的约数和模MOD 对A质因子分解P1^k1*P2^k2....P^kn A^B既指数对应部分乘以B 对于每个P都有(1+P^1+P^2+...+P^ki)的选择 连乘每一个P的等比数列之和即可 ...

  9. 【简●解】POJ 1845 【Sumdiv】

    POJ 1845 [Sumdiv] [题目大意] 给定\(A\)和\(B\),求\(A^B\)的所有约数之和,对\(9901\)取模. (对于全部数据,\(0<= A <= B <= ...

随机推荐

  1. WDS 的两种实现方式

    转自:http://blog.chinaunix.net/uid-26527046-id-3627627.html WDS 的两种实现方式 WDS(Wireless Distribution Syst ...

  2. 多列布局 css3 column属性

    <!doctype html><html lang="en"><head> <meta charset="UTF-8" ...

  3. LCA模板

    /*********--LCA模板--***************/ //设置好静态参数并构建好图的邻接表,然后调用lca_setquery()设置查询 //最后调用lca_start(),在lca ...

  4. MapReduce工作原理

    第一部分:MapReduce工作原理   MapReduce 角色•Client :作业提交发起者.•JobTracker: 初始化作业,分配作业,与TaskTracker通信,协调整个作业.•Tas ...

  5. myeclipse黑色主题怎么还原

    删除workspace-->.metadata-->.plugins-->org.eclipse.core.runtime

  6. js倒计时天时分秒[转]

    <script language="JavaScript"> <!-- // function getQueryString(name) { var reg =n ...

  7. shader学习路线

    http://www.jianshu.com/p/7b9498e58659 http://blog.csdn.net/candycat1992/article/details/37882765

  8. tcp服务的测试程序开源

    开源的是一个测试客户端,可以用来检验服务器端程序的并发处理能力. 使用方法为: python epolltest.py --host=192.168.15.128 --port=8809 --degr ...

  9. mysql 免安装版本 命令安装

    1.down load mysql-5.5.28-win32.zip 2.unzip it to a path such as d:/mysq/mysql-5.5.28-win32 3.copy th ...

  10. DispatcherServlet中使用的特殊的Bean

    DispatcherServlet默认使用WebApplicationContext作为上下文,因此我们来看一下该上下文中有哪些特殊的Bean: 1.Controller:处理器/页面控制器,做的是M ...