前言
自闭,数学差果然是这样的
题目
【问题描述】
我们定义(v(i))表示小于等于(i)的最大素数,(u(i))表示大于(i)的最小素数,求(sum_{i=2}^nfrac{1}{v(i)u(i)})的值,以最简分数的形式输出。
【输入描述】
第一行一个正整数(t),表示测试数据数量
每组测试数据一行一个正整数(n)
【输出描述】
对于每组测试数据输出一个答案。
【样例】
Sample Input
2
2 3
Sample Output
1/6
7/30
【数据范围】
对于(30\%)的数据,(t <= 10,n <= 10^4)
对于(100\%)的数据,(t <= 500,n <= 10^9)
讲解
我们将(v(i),u(i))相同的一些数提出来康康
[sum_{i=1}^{u(i)-v(i)}frac{1}{v(i)u(i)}=frac{1}{v(i)}-frac{1}{u(i)}
]
裂项!
于是对于(n),我们找出(v(n),u(n))
[egin{aligned}
sum_{i=2}^{n}&=sum_{i=2}^{v(n)-1}+sum_{v(n)}^{n}\
&=frac{1}{2}-frac{1}{v(n)}+frac{n-v(n)+1}{u(n)v(n)}\
&=frac{v(n)u(n)-2u(n)+2(n-v(n)+1)}{2v(n)u(n)}
end{aligned}]
然后化简即可
什么?你问我怎么找(v(n),u(n))?
难道没人告诉过你质数在(n)以内的分布大概有(frac{n}{ln n})个?
所以平摊下来我们暴力找只需要(ln n)的时间就可以找到了
甚至还可以用(O(sqrt n))的时间判断质数,这并不会TLE
记得开( exttt{long long})
代码
bool prime(int x)
{
for(int i = 2;i*i <= x;++ i)
if(x % i == 0)
return 0;
return 1;
}
LL gcd(LL x,LL y)
{
if(!y) return x;
return gcd(y,x%y);
}
int main()
{
// freopen("prime_0.in","r",stdin);
// freopen("mine.out","w",stdout);
for(int T = Read(); T ;-- T)
{
n = Read();
if(n == 2) {printf("1/6
");continue;}
LL v = n,u = n+1;
while(!prime(v)) v--;
while(!prime(u)) u++;
LL fz = v*u - 2*u + 2*(n-v+1),fm = 2*v*u;
LL d = gcd(fz,fm);
fz /= d; fm /= d;
Put(fz,'/'),Put(fm,'
');
}
return 0;
}