poj 1845 Sumdiv

点击打开链接poj 1845

思路:数学+二分
分析:
1 题目要求的是A^B的所有因子的和对9901取模
2 先看几个数学定理

1:整数的唯一分解定理(如果A本身就是素数的话,那么本身就是分解式)
任意正整数都有且只有一种方式写出其素因子的乘积表达式。
A = (p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)   其中pi均为素数;
A^B = p1^(k1*B) * p2^(k2*B)*...* pn^(kn*B);
 
2:约数和公式
对于已经分解的整数A = (p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)
则A的所有因子之和为
sum = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... * (1+pn+pn^2+pn^3+...pn^kn)
则A^B的所有的因子之和为
sum = (1+p1+p1^2+...+p1^(a1*B)) *(1+p2+p2^2+...+p2^(a2*B)) *...*(1+pn+pn^2+...+pn^(an*B))

3:同余模公式
(a+b)%m=(a%m+b%m)%m
(a*b)%m=(a%m*b%m)%m
(a-b)%m=(a%m-b%m)%m

3 那么假设我们现在求出了A的分解式的pi和ki,那么现在要求的是约数的和,如果直接进行求解的话肯定是会溢出long long的,所以直接求这个思路是不行的。
我们现在来考虑这两个数组
1+p1+p2+p3+p4+p5+p6+p7 = (1+p1+p2+p3)+p4*(1+p1+p2+p3) = (1+p4)*(1+p1+p2+p3);
1+p1+p2+p3+p4+p5+p6 = (1+p1+p2)+p4*(1+p1+p2) + p3 = (1+p4)*(1+p1+p2) + p3;
那么推广到一般的n,就可以分成n是奇数和n是偶数的情况,然后利用上面的最右边的式子求ans。但是如果直接求是不行的,这个时候你可以仔细观察一下这个式子的一般式
如果n数奇数: (1+p^(n/2+1))*(1+p1+...+p^(n/2)); 如果n是偶数:(1+p^(n/2+1))*(1+p1+...+p^(n/2))+p^(n/2);
根据(1+p1+...+p^(n/2)),这个就是原式的一半,那么根据这个规律我们就可来利用递归每一次都进行二分求解即可。

4 注意取模的运用,像这一类的题目,数据量很大的都是要用long long。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long int64;
#define MAXN 100010
#define MOD 9901

int64 a , b , pos , ans;
int64 p[MAXN] , k[MAXN];

/*求出a的分解式的pi和ki*/
void prime(){
   pos = 0;
   for(int64 i = 2 ; i*i <= a ; i++){
      if(a%i == 0){
        p[pos] = i;
        k[pos] = 0;
        while(a%i == 0){
           k[pos]++;
           a /= i;
        }
        pos++;
      }
   }
   /*假设a本身就是一个素数*/
   if(a != 1){
     p[pos] = a;
     k[pos++] = 1;
   }
}

/*快速幂求次方*/
int64 Pow(int64 x , int64 y){
    int64 tmp = 1;
    while(y){
       if(y&1)
         tmp = (tmp%MOD)*(x%MOD)%MOD;
       y >>= 1;
       x = (x%MOD)*(x%MOD)%MOD;
    }
    return tmp;
}

/*二分求解等比数列的和1+x+x^2+x^3...+x^y*/
int64 sum(int64 x , int64 y){
    if(y == 0)
       return 1;
    /*是奇数*/
    if(y&1)
       return (sum(x , y/2)%MOD)*((1+Pow(x , y/2+1))%MOD)%MOD;
    /*是偶数*/
    else
       return ((((sum(x , y/2-1)%MOD)*((1+Pow(x , y/2+1))%MOD))%MOD) + (Pow(x , y/2)%MOD))%MOD;
}

int main(){
   while(scanf("%lld%lld" , &a , &b) != EOF){
      prime();
      /*求和*/
      ans = 1;
      for(int i = 0 ; i < pos ; i++)
         ans = (ans%MOD)*(sum(p[i] , k[i]*b)%MOD)%MOD;
      printf("%lld\n" , ans);
   }
   return 0;
}
时间: 2024-10-30 13:11:20

poj 1845 Sumdiv的相关文章

POJ 1845 二分+素因子分解

题意:求a^b的因子的和. 对a进行素因子分解a=p1^k1*p2^k2*...*pn^kn则根据成型函数的性质有s=(1+p1+p1^2+p1^3...p1^(k1*b))*....() 等比数列直接二分求前n项和即可. #include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 30000 bool

POJ题目分类

初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      (4)递推.      (5)构造法.(poj3295)      (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996) 二.图算法:      (1)图的深度优先遍历和广度优先遍历.      (2)最短路径算法(dijkstra,bellman-ford

poj系统训练计划

转载:http://www.cnblogs.com/silveryelf/archive/2011/10/29/2228681.html 初级: 基本算法: 枚举:1753    2965 贪心:1328    2109    2586 构造:3295 模拟:1068    2632    1573    2993    2996 图: 最短路径:1860    3259    1062    2253    1125    2240 最小生成树:1789    2485    1258    

POJ:DNA Sorting 特殊的排序

Description One measure of ``unsortedness'' in a sequence is the number of pairs of entries that are out of order with respect to each other. For instance, in the letter sequence ``DAABEC'', this measure is 5, since D is greater than four letters to

POJ 1001 Exponentiation 无限大数的指数乘法 题解

POJ做的很好,本题就是要求一个无限位大的指数乘法结果. 要求基础:无限大数位相乘 额外要求:处理特殊情况的能力 -- 关键是考这个能力了. 所以本题的用例特别重要,再聪明的人也会疏忽某些用例的. 本题对程序健壮性的考查到达了变态级别了. 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/ 某人贴出的测试用例数据地址: http://poj.org/showmessage?message_id=76017 有

POJ 2240 Arbitrage:最短路 Floyd

Arbitrage:http://poj.org/problem?id=2240 大意: 给你m种货币,给你m种货币兑换规则,问通过这些规则最后能不能盈利.eg:1美元换0.5英镑,1英镑换10法郎,1法郎换0.21美元,这样1美元能换0.5*10*0.21=1.05美元,净赚0.05美元. 思路: 用Floyd找出每两种钱之间的最大兑换关系,遍历一遍,看有没有那种钱币最后能盈利,有就输出Yes,没有就是No.在处理钱币名称与编号之间的关系时,可以用map存(比较好用),当然也可以用字符串比较.

POJ 1860 Currency Exchange:最短路 Bellman-Ford

Currency Exchange:http://poj.org/problem?id=1860 大意:有多种货币,之间可以交换,但是需要手续费,也就是说既有汇率又有手续费.问经过交换之后能不能赚. 思路:Bellman_Ford,因为要求最长路,所以松弛条件改一下就好了. Tips: 3              2                  1                20.0货币的数量   兑换点的数量     主人公拥有的货币量    主人公拥有货币的价值1 2 1.00

POJ 1258 Agri-Net:最小生成树 Prim 模版题

Agri-Net:http://poj.org/problem?id=1258 大意:新镇长竞选宣言就是将网络带到每一个农场,给出农场个数,两两之间建光缆的耗费,求所有都联通的最小耗费. 思路:最小生成树,因为边比较稠密,用Prim做. PS:对于比较稠密的图,用Prim,对于比较稀疏的图,用 Kruskal.Kruskal是找边的过程,稀疏的话会比较快. 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/

POJ 1789 Truck History:最小生成树 Prim

Truck History:http://poj.org/problem?id=1789 大意:用一个7位的string代表一个编号,两个编号之间的距离代表这两个编号之间不同字母的个数.一个编号只能由另一个编号变化的来,变化的字母的数量就是这两个编号之间相应的距离,现在要找出一个变化方案,使得总代价最小,也就是距离之和最小. 思路:将每个字符串当成一个节点,求出每个节点之间需要变化的次数为边的权值,用Prim建立最小生成树(稠密图). 更多精彩内容:http://www.bianceng.cnh