专栏文章
题解:P14304 【MX-J27-T1】分块
P14304题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mini7dwb
- 此快照首次捕获于
- 2025/12/02 02:49 3 个月前
- 此快照最后确认于
- 2025/12/02 02:49 3 个月前
题解交迟了所以没申请
题意
给定一个正整数 ,求存在多少个正整数 ,使得 。
思路
如果直接暴力搜索,由于 , 显然会超时。
因此,我们可以考虑手动打表来找规律。我们列出 时所有 的正整数,并判断其是否合法,如下表:

不难发现,对于每一块具有相同的 值的 ,都仅存在 个合法的 ,这三个数分别是 , 和 。
证明过程
-
如果 是个完全平方数,那么显然有 ,又因为 ,故 必定是 的一个因数,且 。
-
如果 是个完全平方数,根据上述结论有 ,整理可得 。又因为 是完全平方数,所以 不是完全平方数,它们的算术平方根向下取整后显然不一样,而且由于取整,两者会相差 ,所以有 。代入 可以得到以下式子:
上式中提出了一个因数 ,所以 必定是 也就是 的一个因数。
- 对于数 ,我们先前已经证明 和 在模 意义下同余,故显然两者相加后再乘 的逆元依旧在模 意义下同余。
接下来就是统计答案,通过上述的表格可以得知, 可以把这若干个 分成 块。我们令 ,显然前 块合法的 总共有 个。
对于最后一块,设最后一块有 个合法的数:
- 如果 在这一块中第一个合法的数 (含) 到第二个合法的数 (不含) 之间,那么 ;
- 如果在第二个合法的数 (含) 到第三个合法的数 (不含) 之间,那么 ;
- 如果正好是第三个合法的数,那么 。
最后答案就是 。
Code
CPP#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
typedef long double ld;
ll q, n, m, ans;
bool issq(ll x){ // 判断是否为完全平方数
ld xx = (ld)sqrt((ld)x);
return xx == (ll)xx;
}
int main()
{
scanf("%lld", &q);
while(q--){
scanf("%lld", &n);
m = (ll)sqrt((ld)n); // 计算能分成多少块
ll l = m * m, r = (m + 1LL) * (m + 1LL), mid = (l + r) >> 1LL; // l, mid, r - 1 分别为最后一块中第一个合法的数,第二个合法的数和第三个合法的数
// 统计
if(n >= l && n < mid) ans = (m - 1LL) * 3LL + 1LL;
else if(n >= mid && n < r - 1LL) ans = (m - 1LL) * 3LL + 2LL;
else if(n == r - 1LL) ans = m * 3LL;
printf("%lld\n", ans); // 输出
}
return 0; // 结束 (。・ω・。)
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...