您的位置:首页 > 其它

【NOIP2016提高A组模拟9.4】快速荷叶叶变换

2016-09-05 14:46 423 查看

题目

Description



Input

一行,包含两个整数N,M。

Output

1个整数,FHT(N,M) mod 1000000007的值。

Sample Input

3 4

Sample Output

1

Data Constraint

40%:n,m<=1000

60%:n,m<=106

100%:n,m<=109

比赛时の想法

一开始看到这道题,就想到了60分的做法,然后就开始想log级别或者是根号级别的做法,过了几分钟,突然想到了一个根号级别的做法:

我们设q=n mod i,p=n div i; 那么我们可以分情况进行讨论:

1:p<=n√,这样的情况最多有n√个,我们直接暴力求解

2:对于剩下的还没有处理的数,他们的p值都是<=n√的,对于每一组p值相等的集合A,集合内所有的数是有等差数列的性质的,那么我们就可以先用二分查找到p值相等的区间(l,r),然后直接用等差数列的算法O(1)计算出这一段数对于答案的贡献,这样我们就可以在n√的时间计算出答案了

正解



贴代码

const md=1000000007;
var
n,m,i,j,k:longint;
x,y,ans,tot,l,r,mid:int64;
procedure init;
begin
readln(n,m);
k:=trunc(sqrt(n));
for i:=1 to n do
begin
if n div i<=k then break;
ans:=ans+(n mod i);
end;
ans:=ans mod md;
end;
begin
init;
if (n=1) or (m=1) then
begin
writeln(0);
halt;
end;
for i:=k downto 1 do
begin
l:=1;
r:=n;
while l<r do
begin
mid:=(l+r) div 2;
if n div mid>=i then l:=mid+1 else r:=mid;
end;
x:=1;
y:=l;
while x<y do
begin
mid:=(x+y) div 2;
if n div mid>i then x:=mid+1 else y:=mid;
end;
l:=x;
while n div l<=i do dec(l);
inc(l);
while n div r<i do dec(r);
if n mod l=0 then inc(l);
x:=n mod l;
if n mod r=0 then dec(r);
y:=n mod r;
mid:=r-l+1;
if l>r then continue;
ans:=(ans+((x+y)*mid) div 2) mod md;
end;
k:=trunc(sqrt(m));
for i:=1 to m do
begin
if m div i<=k then break;
tot:=tot+(m mod i);
end;
tot:=tot mod md;
n:=m;
for i:=k downto 1 do
begin
l:=1;
r:=m;
while l<r do
begin
mid:=(l+r) div 2;
if m div mid>=i then l:=mid+1 else r:=mid;
end;
x:=1;
y:=l;
while x<y do
begin
mid:=(x+y) div 2;
if m div mid>i then x:=mid+1 else y:=mid;
end;
l:=x;
while m div l<=i do dec(l);
inc(l);
while m div r<i do dec(r);
if n mod l=0 then inc(l);
x:=m mod l;
if m mod r=0 then dec(r);
y:=m mod r;
mid:=r-l+1;
if l>r then continue;
tot:=(tot+((x+y)*mid) div 2) mod md;
end;
ans:=ans*tot;
writeln(ans mod md);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: