H-Dividing(数论分块)
参考文章:传送门
题意
- 链接:Dividing
- 对于Legend Tuple(下文称为LT)有以下3种规则:
- (1,k)必然符合要求;
- 如果(n,k)符合要求,则(n+k,k)也符合要求;
- 如果(n,k)符合要求,则(n*k,k)也符合要求。
给出N、K,分别为n、k的范围,问有多少符合要求的LT。
解题思路
我们先固定k,分析n。
对于任意一个k,我们来看满足条件的n。
首先,n=1的时候是LT,那么在乘k和k后,n=k,n=k+1都是LT。不论是乘k还是加k,都不改变n%k的值,始终n%k=0或者n%k=1。
那么也就是计算
∑
k
=
1
K
∑
n
=
1
N
(
n
%
k
=
=
1
∣
∣
n
%
k
=
=
0
)
=
∑
k
=
1
X
N
K
+
∑
k
=
2
Y
(
N
−
1
K
+
1
)
=
∑
k
=
1
X
N
K
+
∑
k
=
2
Y
N
−
1
K
+
K
−
1
X
=
m
i
n
(
N
,
K
)
Y
=
m
i
n
(
N
−
1
,
K
)
\sum\limits_{k=1}^K\,\sum\limits_{n=1}^N\,(\,n\%k==1\;||\;n\%k==0\,)\\[0.5cm]=\,\sum\limits_{k=1}^X\,\frac{N}{K}\,+\,\sum\limits_{k=2}^Y\,(\,\frac{N-1}{K}+1\,)\\[0.5cm]=\,\sum\limits_{k=1}^X\,\frac{N}{K}\,+\,\sum\limits_{k=2}^Y\,\frac{N-1}{K}\,+\,K-1 \\[0.5cm]X=min(N,K) \quad Y=min(N-1,K)
k=1∑Kn=1∑N(n%k==1∣∣n%k==0)=k=1∑XKN+k=2∑Y(KN−1+1)=k=1∑XKN+k=2∑YKN−1+K−1X=min(N,K)Y=min(N−1,K)
显然,数论分块。
不会数论分块的小朋友可以看看以下资料:
1. 文章:数论分块
2. 视频:传送门1+传送门2
代码
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int main()
{
ll N,K;
scanf("%lld%lld",&N,&K);
ll ans=(K-1)%mod;
ll ed=min(N,K);
for(ll l=1,r;l<=ed;l=r+1)
{
r=min(K,N/(N/l));
ans=(ans+(((r-l+1)%mod)*((N/l)%mod))%mod)%mod;
}
N--;
ed=min(N,K);
for(ll l=2,r;l<=ed;l=r+1)
{
r=min(K,N/(N/l));
ans=(ans+(((r-l+1)%mod)*((N/l)%mod))%mod)%mod;
}
printf("%lld\n",ans);
return 0;
}
D-Fake News(签到)
题意
- 链接:Fake News
- 给出n判断下式子是否为完全平方数是则输出"Fake news!" 否则输出 “Nobody knows it better than me!”
∑ k = 1 n k 2 \sum_{k=1}^{n}k^2 k=1∑nk2
解题思路
n达1e15导致现场一直忘复杂想,比如质因数分解判断,万万没想到只需特判就可以,因为1²+2²+…+n² 为平方数的解只有 n=1 或 n=24- 具体证明可见:传送门
代码
#include<stdio.h>
int t,n;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
if(n==1||n==24)printf("Fake news!\n");
else printf("Nobody knows it better than me!\n");
}
return 0;
}