TopCoder SRM596 DIV2 1000: SparseFactorialDiv2

题意:

For an integer n, let F(n) = (n - 0^2) * (n - 1^2) * (n - 2^2) * (n - 3^2) * ... * (n - k^2), where k is the largest integer such that n - k^2 > 0. You are given three long longs lo, hi and divisor. It is guaranteed that divisor will be a prime number. Compute and return the number of integers n between lo and hi, inclusive, such that F(n) is divisible by divisor.

思路:

等价转换关系

整除质数<==>有这个质因子

[lo,hi]<==>[1,hi]  - [1,lo-1]

首先考虑直接整除的。

对于区间[1,x],个数为x/divisor个

其次考虑后面的量

注意到之间是乘法关系。所以每个量都可以考虑。

假设n-k可以被divisor整除,那么相当与n是在每个divisor整除数的后k位。

这里有一个性质:这些n间隔也是divisor

考虑重复问题:如果%divisor相等,则可能重复。

k越小,可包含的区间越大。所以从小到大处理k就好。如果取模出现过,就不计算。因为一定已经被之前的计算过了。

至于计算区间 对于[0,x], k

就是[k+1,x].(如果k>x那就=0,是k+1的原因是题目要求>0,即不能从0偏移k得到。)

个数就是(x-k)/divisor

代码

#define FOR(I,A,B) for(int I = (A); I < (B); ++I)
#define REP(I,N)   FOR(I,0,N)
#define ALL(A)     (A).begin(), (A).end()

class SparseFactorialDiv2
{
public:
    long long getCount(long long lo, long long hi, long long divisor)
    {
        int vis[1000];
        REP(i, 1000) vis[i] = 0;
        long long ans = 0;
        for (long long i = 0; i*i<hi; i++) {
            long long mod = (i*i)%divisor;
            if (!vis[mod]) {
                vis[mod] = 1;
                long long nlo = 0;
                if (lo-1 > i*i) nlo = (lo-1-i*i)/divisor;
                long long nhi = 0;
                nhi = (hi-i*i)/divisor;
                ans += nhi-nlo;
            }
        }
        return ans;
    }
};
View Code

 

 

 

posted on 2013-11-03 15:52  ShineCheng  阅读(406)  评论(0)    收藏  举报

导航