gym 101775 D. Mr. Panda and Geometric Sequence(枚举)

题解:枚举所有情况,关键点在于首先我们先只考虑前三个数,那么重点是第二个数不能超过1e5。

然后我们假设倍数是\frac{q}{p} ,这个式子应该是最简分式,即gcd(q,p) ==1。

假设一个变量k,使得第一个数为:k*p*p,则第二个数为k*p*q,第三个数为k*q*q。如此往下枚举。

然后往后扩展第4,5,......个的时候判断下k%p是否为0即可。

枚举的复杂度大概为O(nlognlogn),因为前两个for循环是调和级数,第三个也差不多。

#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int MX = 1e7+7;
int cnt;
LL a[20];
LL ans[MX];
int popcnt(LL x)
{
    int ret = 0;
    while(x){
        x /= 10;
        ++ret;
    }
    return ret;
}
int solve(LL x)
{
    return upper_bound(ans,ans+cnt,x) - ans;
}
void init()
{
    int n = 1e5;
    a[0] = 1;
    for(int i = 1; i < 16; i++) a[i] = a[i-1]*10;
    for(int p = 1; p <= n; p++){
        for(int q = p+1; q <= n/p; q++){
            if(__gcd(p,q) > 1) continue;
            for(int k = 1; k <= n/p/q; k++){
                LL x = 1LL*k*p*p;
                LL y = 1LL*k*p*q;
                LL z = 1LL*k*q*q;
                int nx = popcnt(x), ny = popcnt(y), nz = popcnt(z);
                int num = nx + ny + nz;
                if(num > 15) break;
                LL lastnum = z, lastv = x*a[ny+nz]+y*a[nz]+z;
                ans[cnt++] = lastv;

                while(1){
                    if(lastnum%p != 0) break;
                    lastnum = lastnum/p*q;
                    num += popcnt(lastnum);
                    if(num > 15) break;
                    lastv = lastv*a[popcnt(lastnum)]+lastnum;
                    ans[cnt++] = lastv;
                }
            }
        }
    }
    sort(ans,ans+cnt);

}

int main()
{
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif // LOCAL
    int T,cas = 0;
    init();
    scanf("%d",&T);
    while(T--) {
        LL l,r;
        scanf("%I64d%I64d",&l,&r);
        printf("Case #%d: %d\n",++cas,solve(r)-solve(l-1));
    }
    return 0;
}

 

你可能感兴趣的:(杂)