题目大意:
题目链接:
洛谷:https://www.luogu.org/problemnew/show/P2261
JZOJ:https://jzoj.net/senior/#main/show/3912
给定,求
思路:
首先暴力打个表。
1- 0
2- 0 0
3- 0 1 0
4- 0 0 1 0
5- 0 1 2 1 0
6- 0 0 0 2 1 0
7- 0 1 1 3 2 1 0
8- 0 0 2 0 3 2 1 0
9- 0 1 0 1 4 3 2 1 0
10- 0 0 1 2 0 4 3 2 1 0
11- 0 1 2 3 1 5 4 3 2 1 0
12- 0 0 0 0 2 0 5 4 3 2 1 0
13- 0 1 1 1 3 1 6 5 4 3 2 1 0
14- 0 0 2 2 4 2 0 6 5 4 3 2 1 0
15- 0 1 0 3 0 3 1 7 6 5 4 3 2 1 0
16- 0 0 1 0 1 4 2 0 7 6 5 4 3 2 1 0
17- 0 1 2 1 2 5 3 1 8 7 6 5 4 3 2 1 0
18- 0 0 0 2 3 0 4 2 0 8 7 6 5 4 3 2 1 0
19- 0 1 1 3 4 1 5 3 1 9 8 7 6 5 4 3 2 1 0
20- 0 0 2 0 0 2 6 4 2 0 9 8 7 6 5 4 3 2 1 0
21- 0 1 0 1 1 3 0 5 3 1 10 9 8 7 6 5 4 3 2 1 0
22- 0 0 1 2 2 4 1 6 4 2 0 10 9 8 7 6 5 4 3 2 1 0
23- 0 1 2 3 3 5 2 7 5 3 1 11 10 9 8 7 6 5 4 3 2 1 0
24- 0 0 0 0 4 0 3 0 6 4 2 0 11 10 9 8 7 6 5 4 3 2 1 0
25- 0 1 1 1 0 1 4 1 7 5 3 1 12 11 10 9 8 7 6 5 4 3 2 1 0
26- 0 0 2 2 1 2 5 2 8 6 4 2 0 12 11 10 9 8 7 6 5 4 3 2 1 0
27- 0 1 0 3 2 3 6 3 0 7 5 3 1 13 12 11 10 9 8 7 6 5 4 3 2 1 0
28- 0 0 1 0 3 4 0 4 1 8 6 4 2 0 13 12 11 10 9 8 7 6 5 4 3 2 1 0
29- 0 1 2 1 4 5 1 5 2 9 7 5 3 1 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
30- 0 0 0 2 0 0 2 6 3 0 8 6 4 2 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
第行的第个数字表示时的答案。(第一列是行标号)。
然后就会发现:
当时,之间的所有数字被除之后的余数是一个公差为的等比数列。(表示向下取整)
那么可以枚举,求出,然后求出项数,最后用等差数列求和公式即可。
但是当时,需要枚举次,会稳稳超时。
所以当时,剩余的数字在左右,直接推出枚举暴力求解即可。
然后就愉快的拿到分。
注意题目没说,所以当时,直接
if (m>n)
{
ans+=(m-n)*n;
m=n;
}
时间复杂度:玄学,大约吧。
代码:
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
ll n,m,ans,a1,an,s,k;
int main()
{
cin>>n>>m;
if (m>n)
{
ans+=(m-n)*n;
m=n;
}
for (ll i=n/m;(n/i)!=(n/(i+1));i++) //枚举i,判断[x/i]和[x/(i+1)]
{
a1=n%min(n/i,m); //首项
an=n%(n/(i+1)+1); //末项
ans+=(a1+an)*(an-a1+i)/i/2; //求和公式
k=n/(i+1)+1; //记录计算到那个位置
}
for (ll i=1;i<k;i++) //剩余暴力求解
ans+=n%i;
cout<<ans<<endl;
return 0;
}