Poj 2800 Joseph's Problem - 找规律

题目大意:给定n和k,求 1<=i<=n(k mod i)

题目分析:n和k很大,直接算会TLE,但是可以先打表找规律。点击可见数学推导

               随便找几组数据可以发现下面的规律

                      1)如果k/i的值相等,那么kmodi的值成等差数列(连续的)

                      2)如果k比n大,那么k/i的值随i的值增大而减小

                      3)如果k比n小,那么kmodi 大于k,当i大于k时

               可见,主要解决的问题就是1),找到连续的成等差数列的区间。因为有规律3),所以不妨从后面往前找。如果发现了前面的规律,那么就会发现下                  面的规律:                 

                      4) 从后往前找,如果从j开始出现等差数列(j为等差数列第一项),那么该等差数列的最后一项为k/(k/j+1)+1 

               但是等差数列不一定出现,如果k/(k/j+1) >= j。

代码:

#include <stdio.h>
long long solve(int n,int k)
{
    long long ans = 0;
    if(n > k)
    {
        ans += (long long)(n-k) * k;
        n = k;
    }
    int div = k/n;
    while(n > 1)
    {
        int id = k/(div+1);
        if(id >= n)
        {
            ans += k % n;
            n--;
            div = k/n;
            continue;
        }
        int s = k%n;
        int e = k%(id+1);
        ans += (((long long )(s+e)*(n-id))>>1);
        n = id;
        div++;
    }
    return ans;
}
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k) != EOF) printf("%lld\n",solve(n,k));
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值