您的位置:首页 > 其它

[Noi2002]Robot 欧拉函数+递推

2017-08-27 14:10 363 查看
题目链接:bzoj1408

—————————————-

概述

题目的意思比较复杂,大致如下:

给定一个数n,将它所有约数分为三类:

能分解成偶数个不同奇质数的乘积.(质因数的指数小于等于1)

能分解成奇数个不同奇质数的乘积.(质因数的指数小于等于1)

不满足1、2的约数.

注:1不算任何数的约数.

例如:对于正整数90:

一类约数:15.

二类约数:3、5.

三类约数:2、6、9、10、18、30、45、90.

现在告诉你正整数n,让你求得其一类约数的欧拉函数之和,二类约数的欧拉函数之和,三类约数的欧拉函数之和。结果均对10000取模。

我们将n质因数分解:n=∏i=1kpeii.

题目将给出k,以及n所有的质因数pi和其指数ei.

—————————————-

题解

我们发现,上面三类约数的并集很显然就是n的所有约数(不包括1)

由于正整数n的欧拉函数有这么一条性质:n=∑d|nφ(d).

(不清楚的可以参考我之前的博客:常见函数讲解1:欧拉函数,其中“扩展性质”中给出了上式的证明)

所以,我们设三类约数的欧拉函数之和分别为Ans1、Ans2、Ans3,那么显然有:Ans1+Ans2+Ans3=n−1.

也就是说,假如我们求得了Ans1、Ans2,那Ans3自然能得知了。

那么我们如何求得Ans1和Ans2呢?

我们发现,对于一个一类约数a=∏mi=1pi,其中m为偶数,我们对a乘一个不属于{p1~pm}的质因数pm+1,那么我们就能把一类约数a变成二类约数a×pm+1.

我们顺着这个思路想,我们用前i−1个质因数构成的一类约数,只要乘上pi那么就能把他们全都变成二类约数了。

设s1i为前i个质因数构成的一类约数的欧拉函数之和,s2i为前i个质因数构成的二类约数的欧拉函数之和。由上面得到的结论,我们可以推出s1与s2之间存在如下的递推关系:s1i=s2i−1×φ(pi).s2i=s1i−1×φ(pi)+φ(pi).

很明显,Ans1=s1k, Ans2=s2k。所以我们只要初始化s10=s20=0,然后O(n)的递推即可得到Ans1和Ans2的值。

至于Ans3嘛,之前得出了Ans3=n−1−Ans1−Ans2这样的结论,直接计算即可。别忘了取模。

—————————————-

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<ctime>
#define ll long long
#define For(i,j,k) for(register int i=j; i<=(int)k; ++i)
#define Forr(i,j,k) for(register int i=j; i>=(int)k; --i)
#define INF 0x3f3f3f3f
using namespace std;

const int mo = 10000;
const int maxn = 1000+5;

int n, x, Ans1, Ans2, Ans3;
int p[maxn], e[maxn];

inline int ksm(int x, int y){
int back = 1;
x %= mo;
while(y){
if(y & 1)   back = back*x%mo;
x = x*x%mo;
y >>= 1;
}
return back;
}

int main(){
scanf("%d", &n);
For(i, 1, n)    scanf("%d%d", &p[i], &e[i]);

int s1, s2;
For(i, 1, n){
if(p[i] == 2)   continue;
s1 = (Ans1 + Ans2*(p[i]-1)%mo)%mo;
s2 = ((Ans2+p[i]-1)%mo + Ans1*(p[i]-1)%mo)%mo;
Ans1 = s1,  Ans2 = s2;//递推求得Ans1和Ans2.
}

x = 1;
For(i, 1, n)
x = x*ksm(p[i], e[i])%mo;//计算n在模10000意义下的值.
Ans3 = (x-Ans1-Ans2-1)%mo;//计算Ans3.
while(Ans3 < 0) Ans3 += mo;//防止Ans3爆负.

printf("%d\n%d\n%d", Ans1, Ans2, Ans3);
return 0;
}


—————————————-

小结

本题的关键在于找到那个递推式计算Ans1和Ans2,结合欧拉函数的性质就能快速计算Ans3。作者想了1h小时无果,膜拜大佬之后便有了灵感。果然,分析性质这儿技能还需要多锻炼才能提高。

—————————————-

——wrote by miraclejzd.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: