1. 程式人生 > >[拆分質因數] 求1e6區間內的數的因數之和 GYM 101652C

[拆分質因數] 求1e6區間內的數的因數之和 GYM 101652C

https://vj.e949.cn/f8d37a96d021442108f4492dfd021271?v=1541730304

 

 

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;

const int mn = 1e6;

int cnt;
bool prime[mn + 10];
int pm[mn + 10];
void Prime()   /// 1e6之內素數表
{
	for (int i = 1; i <= mn; i++)
		prime[i] = 1;

	for (int i = 2; i <= mn; i++)
	{
		if (prime[i] == 0)
			continue;

		pm[++cnt] = i;
		for (int j = 2; i * j <= mn; j++)
			prime[i * j] = 0;
	}
}

ll L, R;
ll val[mn + 10], num[mn + 10][20];
int pcnt[mn + 10], ecnt[mn + 10][20];
void find_prime()
{
	for (int i = 0; i <= R - L; i++)
		val[i] = L + i;

	for (int i = 1; i <= cnt; i++)
    {
        for (ll j = (L - 1) / pm[i] * pm[i] + pm[i]; j <= R; j += pm[i])    /// 範圍內每pm[i]個 因數含pm[i]
        {
            ll id = j - L;
            pcnt[id]++;     // id的因子數+1
            num[id][pcnt[id]] = pm[i];  // 該因子值為pm[i]
            while (val[id] % pm[i] == 0)
            {
                val[id] /= pm[i];
                ecnt[id][pcnt[id]] ++;  // 該因子個數
            }
        }
    }
    
    for (int i = 0; i <= R - L; i++)
    {
        if (val[i] > 1)     /// 有且只有一個大於1e6的因子
        {
            pcnt[i]++;
            num[i][pcnt[i]] = val[i];
            ecnt[i][pcnt[i]]++;
        }
    }
}

int main()
{
	Prime();

	scanf("%lld %lld", &L, &R);

	find_prime();

	ull ans = 0;
	for (ll i = 0; i <= R - L; i++)
	{
		ull tt = 1;
		for (int j = 1; j <= pcnt[i]; j++)
		{
			ull t = 1, temp = 1;
			for (int k = 1; k <= ecnt[i][j]; k++)   // 等比數列求和
			{
				t *= num[i][j];
				temp += t;
			}
			tt *= temp;
		}
		ans += tt;
	}

	printf("%lld\n", ans);

	return 0;
}