luogup3708 koishi的数学题

Posted royal-8

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogup3708 koishi的数学题相关的知识,希望对你有一定的参考价值。

看题,嗯很好。

暴力思路清晰,直接模拟流程20分到手;

再仔细看,好像是一道数学题,思路不太明显。那我们打个表看一下;

那我们就用样例来说明一下

n=10;
f[5]=5%1+5%2+5%3+5%4+5%5+5%6+5%7+5%8+5%9+5%10;
      0   1   2   1   0   5   5   5   5   5
f[6]=6%1+6%2+6%3+6%4+6%5+6%6+6%7+6%8+6%9+6%10;
      0   0   0   2   1   0   6   6   6   6
我们发现f[5]->f[6]是f[5]里每一个数都加1然后再减一些东西得到的;
那我们尝试的加一下;
f[5]=5%1+5%2+5%3+5%4+5%5+5%6+5%7+5%8+5%9+5%10;
      0   1   2   1   0   5   5   5   5   5
      1   2   3   2   1   6   6   6   6   6
比较一下和f[6]的区别,发现少了1 2 3 6四个数,等等,这不是六的正因子之和吗。
那那那f[6]->f[7]呢.,我们发现少的同样是7的正因子之和;
那我们可以猜测一下f[i]的递推式了;
  f[i]=f[i-1]+n-(i的正因子之和);
那考虑证明一下这个式子;
1.相邻两个数(x,y)互质,那么除了1之外,不可能有x%k==0&&y%k==0;(y=x+1)
如果能使x+1%k==0,那么x%k==x;
2.感性理解一下,我们再算f[i]的时候,有可能f[i-1]+1然后%一下变成0了,而我们没有处理这部分,
想象一下x%i=0,那么i是啥,当然是x的因数了,而且包括1;
是不是很开心,我们可以0(n)递推求出答案了,但还有一个问题,i的正因子之和怎么求啊;
1.nlogn的算法 

 num[1]=1;

   for(int i=2;i<=n;i++)

        num[i]=i+1;
    for(int i=2;i*i<=n;i++)
        for(int j=i;j<=n/i;j++)
            if(i==j)
                num[i*j]+=i;
            else
               num[i*j]+=(i+j);

2.因为正因数之和这个函数是积性函数,所以可以用线性筛筛出来(至于如何证这个是积性函数,我就不太会了,不过好像可以用算数基本定理)

void ERS(int maxx)
{
    for(int i=2;i<=maxx;i++)
    {
        if(ipri[i])
        {
            pri[++cnt]=i;
            spri[i]=i+1;//质数的因子和子是自己+1
            facs[i]=i;//质数的最大因子是自己 
        }
        for(int j=1;j<=cnt&&i*pri[j]<=maxx;j++)
        {
            int noww=i*pri[j];
            ipri[noww]=false;
            facs[noww]=pri[j];//更新 
            if(!(i%pri[j]))//发现i是枚举到的质数的倍数,准备跳车
            {
                facs[noww]=facs[i]*pri[j];//积性函数性质,更新 
                if(facs[noww]==noww)//最大因子就是自己说明这个数的facs已经更新完了,该更新spri了
                    for(int k=1;k<=noww;k*=pri[j]) 
                        spri[noww]+=k;//因为i是枚举到的质数的倍数,用加法更新即可  
                else 
                    spri[noww]=spri[facs[noww]]*spri[noww/facs[noww]];//注意这里更新,下面就break掉了 
                break;
            }
            spri[noww]=spri[pri[j]]*spri[i];//积性函数性质,更新 
        }
    }
} } 

求出正因数之和,那么这道题不就非常愉悦的A掉了

技术分享图片
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
long long num[1200000],n,f[1200000];
int main()
{
    scanf("%lld",&n);
        num[1]=1;
    for(int i=2;i<=n;i++)
        num[i]=i+1;
    for(int i=2;i*i<=n;i++)
        for(int j=i;j<=n/i;j++)
            if(i==j)
                num[i*j]+=i;
            else
               num[i*j]+=(i+j);
    f[1]=n-1;
    for(register int i=2;i<=n;i++)
        f[i]=f[i-1]+n-num[i];
    for(register int i=1;i<=n;i++)
        printf("%lld ",f[i]);    
    return 0;
}
由于我不知道为啥是积性函数,所以就用了第一种(标程)




















以上是关于luogup3708 koishi的数学题的主要内容,如果未能解决你的问题,请参考以下文章

P3708 koishi的数学题(因数和)

lg3708 koishi的数学题 [数学]

C 洛谷 P3599 Koishi Loves Construction [构造 打表观察]

luoguP3768简单的数学题

luoguP1062 数列 [数学]

D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]