题意:给出n,k;
求,
k mod i =k-i*(k/i)
= n*k - (1*(k/1)+2*(k/2)+3*(k/3)+.....n*(k/n))
我们发现 当 i >k 时 k/i=0,不必计算
k/k, k/(k-1),............. k/(k/2+1) k/i=1; 即k*(k/k) + (k-1)*( k/(k-1))+.............(k/2+1)*( k/(k/2+1))= 1*西柯玛(k~(k/2+1))
k/(k/2) , k/(k/2-1) ,............,k/(k/3+1) k/i=2; 即(k/2)*(k/(k/2) ) + (k/2-1)*(k/(k/2-1) )+............(k/3+1)*(k/(k/3+1))= 2*西柯玛((k/2)~(k/3+1))
往后类推,需要计算的会比较小,应该是log级别的复杂度,太菜,不会算,也不知道对不对,希望知道的大佬留言区教教我
代码风格也丑的一匹。。。。。。。
#include<stdio.h>
using namespace std;
long long p(long long b,long long e)
{
if((b+e)&1) return ((e-b+1)/2)*(b+e);
return ((b+e)/2)*(e-b+1);
}
int main()
{
long long n,k,a,b;
while(~scanf("%lld%lld",&n,&k))
{
long long ans=n*k;
// (k mod (1-n))
// k-i*(k/i)
// n*k-(1*(k/1)+2*(k/2)+3*(k/3)+.....n*(k/n))
// n*k-(1*(k/1)+2*(k/2)+3*(k/3)+..... +((k/2)+1)*(k/(2)+1).....k*(k/k)+0+0+000000.....)
long long i=2;
while(1)
{
if(k/i<n)
{
if(n>k) b=k+1;
else b=n+1;
break;
}
i++;
}
for(;;i++)
{
a=b-1;
b=(k/i+1);
if(a==b) break;
ans-=((i-1)*p(b,a));
}
for(i=a;i>=1;i--)
ans-=(i*(k/i));
printf("%lld\n",ans);
}
return 0;
}
分块模板
#include<stdio.h>
#include<algorithm>
using namespace std;
long long sum(long long b,long long e)
{
if((b+e)&1) return ((e-b+1)/2)*(b+e);
return ((b+e)/2)*(e-b+1);
}
long long clac(long long k,long long n)
{
long long ans=0;
int Min=min(k,n);
for (int i = 1, la = 0; i <= Min; i = la + 1)
{
la=k/(k/i);
if(la>Min) la=Min;
// printf("i=%d la=%d\n",i,la);
ans +=sum(i,la)*(k/i); //区间[i,la]为一块
}
return ans;
}
int main()
{
long long n,k,ans;
while(~scanf("%lld%lld",&n,&k))
{
ans=n*k;
ans-=clac(k,n);
printf("%lld\n",ans);
}
return 0;
}