POJ 2800 Joseph’s Problem 数论找规律

Description 
 
Input 
两个整数n和k(1<=n,k<=1e9) 
Output 
输出 
Sample Input 
5 3 
Sample Output 
7

暴力超时,这样就打下表找下余数的规律。输入100,27,一下子就可以看出来,倒着的看,是一段一段的等差序列。

例如100 25

除数 1    2    3    4    5    6    7    8    9     10     11    12   13 14  15  ......25   26........

商  25  12   8    6    5    4    3    3    2     2       2      2      1   1   1   ........1    0.....

这里可以看到商的变化前面很大,从5后面开始稳定下来,观察,其实就是sqrt(k),前面除数数小,商的变化就大,这个临界点也与求质数打表那个相似,从2~sqrt(质数),遍历判断,如果没有能整除的即为质数,这两个的数学原理好像是相同的,想想为什么?

sqrt(k) = e;

然后我们利用除数来求等差数列的区间。也就是枚举商sqrt(k)~1,左区间p1 =  k/e+1,得的是左区间,然后k/(e-1)得右区间,注意e这个除数其实不是起点,得到相同商的第一个起点是e+1,然后利用e-1得到这个相同的商的最大的一个除数,比如25/3=8,这个等差区间的最后一个,25/2=12,这个等差区间的最后一个。

除数i大于k的部分,数量是n-k,然后直接k*(n-k)

小于sqrt(k)的部分直接枚举就行了

****然后之前还有一个问题,按照HJ的写发,p1是k/e,是相同商的前一个区间的最后一个数,所以求和公式,数量不用+1,但是上底+1,再加下底,他的这个写发有一个问题是:

上面例子 n=8的时候,3 3这两个商的区间在i=4的时候算完了,然后i=3,p1=8,p2=12大于n了,p2=8,然后求和相减等于0,这部分其实多算了一遍,区间就已经没有了。跳出的上一个循环肯定是完成了p2=n的操作。比如继续p1=25/2=12明显大于n了,跳出。按照我这种写法,n=8,算完除数为3的,p1=9直接跳出了。********

总思想其实就是:这个等差序列的第一个是前一个等差序列最大除数的下一个,最后一个就是这个等差序列的最大除数,在代码的循环里面也是循环到2就结束,因为2算的就是商为1的情况。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int main()
{
    freopen("joseph.in","r",stdin);
    freopen("joseph.out","w",stdout);
    ll n,k;
    while(~scanf("%I64d%I64d",&n,&k))
    {

        ll sum=0;
        //第三部分
        if(n>k)
            sum+=(n-k)*k;
        ll e=sqrt(1.0*k);
        ll p=k/e;
        //第一部分
        for(int i=1;i<=n && i<=p;i++)
            sum+=k%i;
        //第二部分
        for(int i=e;i>1;i--)
        {
            ll p1=k/i + 1;
            ll p2=k/(i-1);

            //n小于左区间了就直接退出了
            if(p1>n)
                break;

            //当n的大小小于这段等差数列区间的最后一个值
            if(p2>n)
                p2=n;

            sum+=(k%(p1)+k%p2)*(p2-p1+1)/2;//等腰求和
        }
        printf("%I64d\n",sum);
    }
    return 0;
}
时间: 2024-12-10 23:17:09

POJ 2800 Joseph’s Problem 数论找规律的相关文章

POJ 2800 Joseph&#39;s Problem

给n 和 k 求: ∑1<=i<=n(k mod i). p  = k/i k mod i = k - p * i k mod ( i + 1 ) = k - p * ( i + 1 ) = k mod i - p k mod ( i + 2 ) = k - p * ( i + 2 ) = k mod i - 2 * p 对于连续的 i ,很多p都是一样的 . 相差的部分是一个等差数列 , i 的 范围是 从 i 到 min(k/p,n) 如果 p == 0 则 一直延续到最后 Joseph'

FOJ有奖月赛-2016年8月 Problem A Daxia &amp; Wzc&#39;s problem(找规律)

Problem A Daxia & Wzc's problem Accept: 42    Submit: 228Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description Daxia在2016年5月期间去瑞士度蜜月,顺便拜访了Wzc,Wzc给他出了一个问题: Wzc给Daxia等差数列A(0),告诉Daxia首项a和公差d; 首先让Daxia求出数列A(0)前n项和,得到新数列A(1); 然后让Daxia求出数列A(

UVa1363 - Joseph&#39;s Problem(数论)

在题目中有三种情况: 1.1<k<n: 2.k == n ; 3.k>n; 对于第一种情况我们可以分为1到k和k到n两个子问题来解. 1.1.1到k: for( i = 1 , sum = 0 ; i <= k ; i ++ ) sum += k %i ; 1.2.k到n: sum =(n-k)*k; 而对于第二种情况就是第一种情况的(1).但是就这样写的话时明显的tle的. 对于第二种情况也可以分为几个小问题来求解: 2.1.1到k/2: for( i = k/2 ; i >

UVA 1363 - Joseph&#39;s Problem(数论)

UVA 1363 - Joseph's Problem 题目链接 题意:给定n, k,求出∑ni=1(k mod i) 思路:由于n和k都很大,直接暴力是行不通的,然后在纸上画了一些情况,就发现其实对于k/i相同的那些项是形成等差数列的,于是就可以把整个序列进行拆分成[k,k/2],[k/2, k/3], [k/3,k/4]...k[k/a, k/b]这样的等差数列,利用大步小步算法思想,这里a枚举到sqrt(k)就可以了,这样就还剩下[1,k/a]的序列需要去枚举,总时间复杂度为O(sqrt(

Codeforces 837E Vasya&#39;s Function 数论 找规律

题意:定义F(a,0) = 0,F(a,b) = 1 + F(a,b - GCD(a,b).给定 x 和 y (<=1e12)求F(x,y). 题解:a=A*GCD(a,b) b=B*GCD(a,b),那么b-GCD(a,b) = (B-1)*GCD(a,b),如果此时A和B-1依然互质,那么GCD不变下一次还是要执行b-GCD(a,b).那么GCD什么时候才会变化呢?就是说找到一个最小的S,使得(B-S)%T=0其中T是a的任意一个因子.变形得到:B%T=S于是我们知道S=min(B%T).也

组队赛#1 解题总结 ZOJ 3798 Abs Problem (找规律+打表)

Abs Problem Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge Alice and Bob is playing a game, and this time the game is all about the absolute value! Alice has N different positive integers, and each number is not greater than N.

POJ 2663 Tri Tiling dp 画图找规律

状态:d[i]代表n=i时的方案数. 状态转移方程:d[i]=d[i-2]+2*(d[i-2]+d[i-4]+…+d[0]) i只会为偶数,奇数情况不存在,d[0]=1 找状态转移方程的时候画图更好理解. #include <iostream> #include <cstdio> #include <algorithm> using namespace std; int d[50]; int main() { int n; d[0]=1; d[2]=3; int sum

POJ 2484 A Funny Game(找规律)

题目链接 #include<iostream> #include<cstdio> using namespace std; int main() { int n; while(scanf("%d",&n)&&n) {//alice先把环破坏,变成链,然后bob只要在链中间取1或2个 //连续的coins,让链变成左右对称的两条,bob就必胜 if(n==1||n==2) printf("Alice\n"); else

HDU2608-0 or 1(数论+找规律)

一,题意: 给定一个n,定义S(n)=T(1)+T(2)+T(3)+...+T(n),T(n)是n的所有因子之和,最后输出S(n)%2的值 (因子就是所有可以整除这个数的数,不包括这个数自身)二,思路: 凡是"能被完全开方的"或者"被2整除后能完全开方"的数i,它的(T(i)%2)=1;       i = 1, 2,  3,   4,   5,   6,   7,     8,    9,   10;    i*i = 1, 4,  9,  16, 25, 36,