NEERC2005主页在这里。
题目给定n和k,要求
。
我们先找一下规律,发现与等差数列是有关系的。我们对于当前的i,令
,
。那么当i增大1时,如果q不变,p一定减少了q,那么将p一直减小到0,同时对这一段进行求和(用数列求和公式),同时i增大到下一段的开头。
详细情况见代码:
#include <cstdio>
#include <algorithm>
using namespace std;
int n,k;
__int64 sum(int a,int d,int n) {
return (__int64)(2*a-d*n)*(n+1)/2;
}
int main() {
freopen("joseph.in","r",stdin);
freopen("joseph.out","w",stdout);
scanf("%d%d",&n,&k);
int i = 1,p,q,a;
__int64 r = 0;
while (i<=n) {
q = k%i; p = k/i;
if (p>0) a = q/p;
else a = INT_MAX;
r += sum(q,p,min(a,n-i));
i += min(a,n-i)+1;
}
printf("%I64d\n",r);
return 0;
}
。我们可以联想其形式:
。那么当n>1时我们也来类比一下相对应的公式。
表示题目中所要求的答案。我们发现,当m为素数时,
。这是显然的,因为除了(m,m,...,m,m)这一组数字以外,其余的都是可行的解。那么m不为素数时,我们把m的各个素因数分开考虑。如果某个素因数被n个数所共有,那么一共就少了
种方案,考察m所有的素因数,我们得到
。