UVa 11876 - N + NOD (N)

来源:互联网 发布:手机医院挂号软件 编辑:程序博客网 时间:2024/05/21 20:57

題目:題目給出公式,Ni = Ni-1 + NOD(Ni-1),NOD为因子个数,求一个区间[A,B]上有多少个N。

分析:数论,dp,打表。打表计算,查询输出。

            首先,打表计算出1000000内的所有素数;

            然后,利用素数表,计算1000000内所有数字的因子个数(组合数学,每个因子个数+1相乘);

            之后,计算N,然后dp计算区间[0,i]的N个个数S(i);

            最后输出S(B)- S(A-1)。

說明:╮(╯▽╰)╭。

#include <cstring>#include <cstdio>int visit[1000001];int prime[1000001];int divid[1000001];int N[1000001];int M[1000001];int S[1000001];int main(){//打表计算素数 memset(visit, 0, sizeof(visit));int count = 0;for (int i = 2; i < 1000001; ++ i)if (!visit[i]) {prime[count ++] = i;for (int j = i+i; j < 1000001; j += i)visit[j] = 1;}//计算因数个数 memset(divid, 0, sizeof(divid));divid[0] = 0; divid[1] = 1;for (int i = 2; i < 1000001; ++ i) {int value = i, ans = 1, move = 0;while (visit[value] && value > 1) {int size = 0;while (value%prime[move] == 0) {value /= prime[move];size ++;}move ++;ans *= (size+1);}if (value > 1) ans *= 2;divid[i] = ans;}//计算N对应的映射 memset(M, 0, sizeof(M));M[N[0] = 1] = 1;for (int i = 1; i < 1000001; ++ i) {N[i] = N[i-1] + divid[N[i-1]];if (N[i] > 1000000) break;M[N[i]] = 1;}//计算对应区间[0, i]内N总数 memset(S, 0, sizeof(S));for (int i = 1; i < 1000001; ++ i)S[i] = S[i-1] + M[i];int T, A, B;while (~scanf("%d",&T))for (int t = 1; t <= T; ++ t){scanf("%d%d",&A,&B);printf("Case %d: %d\n",t,S[B]-S[A-1]);}     return 0;}


0 0
原创粉丝点击