zoukankan      html  css  js  c++  java
  • POJ 2800 Joseph’s Problem 数论找规律

    Description 
    这里写图片描述 
    Input 
    两个整数n和k(1<=n,k<=1e9) 
    Output 
    输出这里写图片描述 
    Sample Input 
    5 3 
    Sample Output 

    暴力超时,这样就打下表找下余数的规律。输入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
    ",sum);
        }
        return 0;
    }
  • 相关阅读:
    API之绘图函数
    DotNetCharting
    Rule engine
    股票
    PHP
    获取Excel.dll
    Excel develop
    几个不错的开源的.net界面控件[转贴]
    关于EXCEL文件双击打不开的问题
    Regular expression
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/6954041.html
Copyright © 2011-2022 走看看