UVa 1363 约瑟夫的数论问题

本文探讨了一道关于模运算求和的问题,通过分析发现当n大于k时的特殊情况,并利用等差数列的性质解决该问题。作者分享了在解决过程中遇到的溢出问题及解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

题目链接

题意:

给定n, k,求出ni=1(k mod       i )

分析:

这题不难,但是我一直WA了七次,我的思路跟书上的是一样的,一直找错误,一直WA,但一直找不到我哪里错了,后来无奈,看了刘汝佳的代码,他实现起来没有讨论k和n谁小谁大,直接比较的,而我先讨论了,n>=k的情况(因为这时候,对于所有的i>k,ans都要加上k),然后再用等差公式求解n<k的情况,思路是对的,但是我没有考虑到(n-k)*k会溢出,所以WA了好多次,所以写下了为以后提个醒。

看个例子n=10,k=8;

求和i从1到n: 0 0 2 0 3 2 1 0 8 8

可以看出,对于i>k,以后的所有数,都是+8,对于i<K的数,其中有一个明显的规律,3 2 1 0这是一个等差数列,d=-1,而1==k/i(i为5 6 7 8),整段长度处在2个0之间,也就是k可以整除的2个数之间,所以根据这个规律就可求了。具体参考代码。

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k)){
        ll ans=0;
        if(n>k)ans=(ll)(n-k)*k,n=k-1; //这里要注意,会爆int,完全没考虑到这里。。
        int i=1,j;
        while(i<=n){
            int p=k/i;
            int m=k%i;
            if(m==0){
                i++;continue;
            }
            j=k/p; //j是k的整除位置
            if(j>n)j=n;
            int num=j-i+1;
            ans+=(ll)num*m-(ll)num*(num-1)/2*p; //等差数列公式n*a1+(n)*(n-1)/2*d
            i=j+1;
        }
        cout<<ans<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值