Codeforces Gym 101775D Mr. Panda and Geometric Sequence(2017-2018 ACM-ICPC Asia East Continent Leagu...

题目链接  ECL-Final 2017 Problem D

题意  给定$2*10^{5}$组询问,每个询问求$l$到$r$之间有多少个符合条件的数

如果一个数小于等于$10^{15}$, 并且能被分割成一个至少有$3$项的递增等比数列(公比可以不为整数)

那么这个数是符合条件的。

 

比赛的时候我大概觉得这应该不是数位DP,是一个比较trick的枚举题。

但是我总感觉哪个地方不太对,或者说是没有写这道题的意识,一直瘫在那里。

今天AC了这个题之后真的后悔莫及,但是一点用都没有。

 

从至少有$3$项这个条件入手。

假设数列只有$3$项。

因为数列递增,所以第二项一定不超过$10^{5}$,

所以等比数列的公比

$\frac{q}{p} <= \frac{a_{2}}{a_{1}} <= a_{2} <= 10^{5}$

设第一项为$kp^{2}$, 第二项为$kpq$, 第三项为$kq^{2}$

那么$kpq <= 10^{5}$,即$pq <= 10^{5}$;

枚举符合条件的$p$和$q$,发现枚举量不超过$4*10^{5}$;

在这个基础上枚举$k$,然后求出整个数列,并考虑那些项数大于$3$的数列,

最后sort一下二分查找就可以了。

 

#include <ctime>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef long long LL;

const int N = 1e5 + 10;

LL a[N * 100];
LL ten[20];
LL l, r;
int cnt = 0;
int T, ca = 0;

int solve(LL x){ return upper_bound(a + 1, a + cnt + 1, x) - a - 1; }

inline int calc(LL x){
	int ret = 0;
	for (; x; x /= 10) ++ret;
	return ret;
}

LL mer(LL x, LL y){ return x * ten[calc(y)] + y; }

int main(){

	ten[0] = 1ll;
	rep(i, 1, 18) ten[i] = ten[i - 1] * 10ll;

	rep(p, 1, 1e5){
		rep(q, p + 1, 1e5){
			if (1ll * p * q >= 1e5) break;
			if (__gcd(p, q) > 1) continue;

			rep(k, 1, 1e5 / p / q){
				LL x = 1ll * k * p * p;
				LL y = 1ll * k * p * q;
				LL z = 1ll * k * q * q;

				int cnt_len = calc(x) + calc(y) + calc(z);
				if (cnt_len > 15) break;

				LL now = mer(mer(x, y), z);
				a[++cnt] = now;

				while (true){
					if (calc(z) >= 9) break;
					if (z * z % y > 0) break;
					LL nw = z * z / y;
					int nwlen = calc(nw);
					if (cnt_len + nwlen > 15) break;
					cnt_len += nwlen;
					now = mer(now, nw);
					a[++cnt] = now;
					y = z;
					z = nw;
				}
			}
		}
	}

	sort(a + 1, a + cnt + 1);
	scanf("%d", &T);
	while (T--){
		scanf("%lld%lld", &l, &r);
		printf("Case #%d: %d\n", ++ca, solve(r) - solve(l - 1));
	}

	return 0;
}

 

转载于:https://www.cnblogs.com/cxhscst2/p/8877625.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值