AcWing - 97 - 约数之和(分治、因数和)

题目链接
??我们首先要知道怎么来求A的约数之和。首先,把A分解质因数,可得:\(A = q1^{k1}\times q2^{k2} ... \times \ qn^{kn}\)
然后我们用乘法的分配律可得A的因数之和为\(F(A) = (q1^0 + q1^1 + ... + q1^{k1}) \times (q2^0 + q2^1 + ... + q2^{k2})\ ... \times \ (qn^0 + qn^1 + ... + qn^{kn})\)
??那么对于\(A^B\)来说,\(A^B = q1^{k1\times B}\times q2^{k2\times B} ... \times \ qn^{kn\times B}\),\(F(A^B) = (q1^0 + q1^B + ... + q1^{k1\times B}) \times (q2^0 + q2^B + ... + q2^{k2\times B})\ ... \times \ (qn^0 + qn^B + ... + qn^{kn\times B})\)
所以说,我们只要求出来所有因数的所有幂次之和这道题就能很容易的求出来了\(q^0 + q^B + ... + q^{k\times B}\),但是我们发现\(k\times B\)看起来并不好求,用暴力的方法显然会超时,关于这个式子的求法可以看这里

//https://www.cnblogs.com/shuitiangong/
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl '\n'
#define rtl rt<<1
#define rtr rt<<1|1
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define maxx(a, b) (a > b ? a : b)
#define minn(a, b) (a < b ? a : b)
#define zero(a) memset(a, 0, sizeof(a))
#define INF(a) memset(a, 0x3f, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("==================================================\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> P2;
const double pi = acos(-1.0);
const double eps = 1e-7;
const ll MOD =  9901;
const int INF = 0x3f3f3f3f;
const int _NAN = -0x3f3f3f3f;
const double EULC = 0.5772156649015328;
const int NIL = -1;
template<typename T> void read(T &x){
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
const int maxn = 1e4+10;
P fac[maxn];
ll a, b; int kase;
void solve(int a) { //分解因数
    int t = a; kase = 0;
    for (int i = 2; i*i<=t && a!=1; ++i) {
        ll cnt = 0;
        while(!(a%i)) {
            a /= i;
            ++cnt;
        }
        if (cnt) fac[kase++] = P(i, cnt*b);
    }
    if (a>1) fac[kase++] = P(a, b); //如果a本身就是素数,那么a的因数就只有1和自己
}
ll solve2(ll x, int y) { //快速幂
    ll ans = 1; x %= MOD;
    while(y) {
        if (y&1) ans = ans*x%MOD;
        x = x*x%MOD;
        y >>= 1;
    }
    return ans;
}
ll solve3(ll a, ll b) { //计算每个因数所有幂次的累加和
    if (!b) return 1;
    ll res = 1;
    if (b&1) res = res*(1+solve2(a, b/2+1))%MOD*solve3(a, b/2)%MOD;
    else res = res*(((1+solve2(a, b/2))*solve3(a, b/2-1)%MOD + solve2(a, b))%MOD)%MOD;
    return res;
}
int main(void) {
    while(cin >> a >> b) {
        if (!a) {
            cout << 0 << endl;
            continue;
        }
        solve(a);
        ll ans = 1;
        for (int i = 0; i<kase; ++i)
            ans = ans*solve3(fac[i].first, fac[i].second)%MOD;
        cout << ans << endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/shuitiangong/p/12538482.html

时间: 2024-11-09 01:39:14

AcWing - 97 - 约数之和(分治、因数和)的相关文章

数学:求一个数的真约数(因数)的个数及所有约数之和

一. 我们知道,每个自然数(不包括0和1)都有2个以上的因数,因数最少的是质数(也叫素数),质数的因数是1和它本身.非质数的自然数也叫合数,它们都含有3个以上(含3个)的因数. 1.怎样求一个数有多少个因数? 对于一个已知的自然数,要求出它有多少个因数,可用下列方法: 首先将这个已知数分解质因数,将此数化成几个质数幂的连乘形式,然后把这些质数的指数分别加一,再相乘,求出来的积就是我们要的结果. 例如:求360有多少个因数. 因为360分解质因数可表示为:360=2^3×3^2×5,2.3.5的指

51nod 1220 约数之和(杜教筛 + 推推推推推公式)

题意 给出\(n(1\leq n \leq 10^9)\),求\(\sum_{i=1}^n\sum_{j=1}^n\sigma(ij)\),其中\(\sigma(n)\)表示\(n\)的约数之和. balabala 交了两道杜教筛的的板子题(51nod 1239, 1244)就看到了这题,然后不会搞,然后看题解看了一天一夜终于彻底搞明白一发A掉了...感觉学到了很多,写个博客整理一下,如有错请指出. 技能需求 数论函数与线性筛 莫比乌斯反演(也可以当成容斥去理解) 狄利克雷卷积 杜教筛 强大的数

(c语法百题20)约数之和

知识点: 求约数的算法 for语句,if语句灵活运用. 内容: 键入一个自然数 ,求这个自然数的所有约数之和 输入说明: 一个整数 输出说明: 一个整数 输入样例: 6 输出样例: 12 1 #include <stdio.h> 2 int main() 3 { 4 int n,s=0,i; 5 scanf("%d",&n); 6 for (i=1;i<=n;i++) 7 { 8 if (n%i==0) 9 { 10 s=s+i; 11 } 12 } 13 p

【动态规划】mr359-最大公约数之和

[题目大意] 选取和不超过S的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大. 输入一个正整数S. 输出最大的约数之和. 样例输入 Sample Input 11 样例输出 Sample Output 9 样例说明 取数字4和6,可以得到最大值(1+2)+(1+2+3)=9. 数据规模对于30%的数据,S≤10: 对于100%的数据,S≤1000. [思路] 水题,普通的01背包问题,唯一需要注意的一点是,1的所有约数之和是0!我一开始就因为1没有单独判断而导致了错误. 1 #inc

POJ1845Sumdiv题解--约数之和

题目链接 https://cn.vjudge.net/problem/POJ-1845 分析 \(POJ\)里的数学题总是这么妙啊 首先有一个结论就是\(A=\prod{ \ {p_i}^{c_i} \ }\),那么\(A\)所有约数之和为\((1+p_1+p_1^2+..+p_1^{c_1}) * (1+p_2+p_2^2+...+p_2^{c_2}) ... (1+p_n +p_n^2 +... + p_n^{c_n})\) 这个好像数学归纳法可证,但是感性理解一下也不难 于是这道题就是求\

51nod 1220 约数之和

约数之和 Problem d(k)表示k的所有约数的和.d(6) = 1 + 2 + 3 + 6 = 12. 定义S(N) = ∑1<=i<=N ∑1<=j<=N d(i*j). 例如:S(3) = d(1) + d(2) + d(3) + d(2) + d(4) + d(6) + d(3) + d(6) + d(9) = 59,S(1000) = 563576517282. 给出正整数N,求S(N),由于结果可能会很大,输出Mod 1000000007(10^9 + 7)的结果.

19: 约数之和

19 约数之和 作者: 朱星垠 时间限制: 1S 章节: 循环 问题描述 : 输入一个正整数(小于1000),计算这个正整数所有约数的和,并打印输出. 输入说明 : 你的程序需要从标准输入设备(通常为键盘)中读入多组测试数据.每组输入数据由一行组成,每行为一个正整数. 输出说明 : 对每组测试数据,你的程序需要向标准输出文件(通常为启动该程序的文本终端)依次输出一组对应的答案:这个正整数所有约数的和,所有数据前后没有多余的空行,两组数据之间也没有多余的空行. 输入范例 : 1 10 输出范例 :

Sumdiv POJ - 1845 A^b约数之和取模 内部递归 外部分治

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

51nod 1348 乘积之和 分治 + fft

给出由N个正整数组成的数组A,有Q次查询,每个查询包含一个整数K,从数组A中任选K个(K <= N)把他们乘在一起得到一个乘积.求所有不同的方案得到的乘积之和,由于结果巨大,输出Mod 100003的结果即可.例如:1 2 3,从中任选1个共3种方法,{1} {2} {3},和为6.从中任选2个共3种方法,{1 2} {1 3} {2 3},和为2 + 3 + 6 = 11. 预处理 + O(1)回答 很容易想到用分治来做,这样在分治过程中需要一个dp,这个dp递推式是O(n^2)的, 所以复杂