题目背景
万人血书 KHIN 完成女装 flag(1/10000) \to→ 万人血书 KHIN 完成女装 flag(2/10000)(1/5000) \to→ 万人血书 KHIN 完成女装 flag(2/5000)(1/2500) \to→ 万人血书 KHIN 完成女装 flag(2/2500)(1/1250) \to→ 万人血书 KHIN 完成女装 flag(2/1250)(1/625) \cdots⋯ 以此类推,在可以约分的情况下,“万人血书”很快就能完成。
题目描述
“x 人血书”的过程可以看成一个函数f(x):
有一个 0/x 的分数。重复以下步骤直到这个分数为 1:
- 分子 +1。
- 如果这个分数可以约分,约分到最简形式。
现在小 D 给了你 T 组数据,每组数据都是给定 n,求在1≤x≤n 的情况下 f(x) 的最大操作次数。
但是他太菜了,不会,你能帮帮他吗?
输入格式
第一行一个正整数 T。
接下来 T 行,每行一个正整数 n。
输出格式
共 T 行,每行一个整数 s 表示在 1≤x≤n 的情况下 f(x) 的最大操作次数。
输入输出样例
输入 #1复制
5 1 2 5 8 114514
输出 #1复制
1 2 5 7 114493
说明/提示
样例解释
f(1)=1,f(2)=2,f(3)=3,f(4)=3,f(5)=5
我也想把更大的 f(x) 列出来,但是地方不够了。
数据范围
对于全部数据,1≤T≤5×10^5,1≤n≤2×10^6。
Subtask 中没填的部分表示和全部数据的范围一样。
洛谷月赛题,难度是普及/提高-
其实难度不大,但思路不好找,因为数据量太大了,一般筛法根本无法AC
下面是我的思路:(虽然能AC但是极慢。。。)
这道题说的挺玄乎,其实就是输出小于n的最大质数,因为质数必定与分子互质,所以不会进行约分,次数自然就是最大了。
筛选也不难,一个函数即可。
可关键在于,1≤T≤5×10^5,1≤n≤2×10^6的数据量意味着我们不能直接在输入n时再进行推质数,需要提前推好所有数据。
很简单,设好边界条件(f[1]=1;f[2]=2),进行递推即可。
不过数据过大,还需用到快读快写
#include <bits/stdc++.h>
using namespace std;
int t;
long long n;
int f[2000001];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void write(int x){
if(x>9) write(x/10);
putchar(x%10+'0');
}
bool isprime(int t) {
if (t%2==0) {
return false;
}
for (int i = 3; i <= sqrt(t); i+=2) {
if (t % i == 0)
return false;
}
return true;
}
int main() {
t=read();
f[1]=1;
f[2]=2;
int i=3;
while (i<=2000001) {
if (isprime(i)) f[i]=i;
else f[i]=f[i-1];
i++;
}
for (int i=1;i<=t;i++) {
n=read();
write(f[n]);
putchar('\n');
}
return 0;
}
(这道题优化半小时才过,还用了6.65s,求神犇指教一百多毫秒是怎么做到的。。。)