[数论][SDOI2012]Longge的问题

SDOI竟然考POJ原题。。。

首先很容易发现答案是ans=Σi*phi(n/i)  (其中i是n的约数)

但是这样求需要所有的phi(n) 时间太长

考虑化简。由phi的公式可得ans=n*Σ ∏(1-1/pai)    (其中pai是n的约数因式分解的素因子)

但还是太慢。

这道题的关键是积性函数,所谓积性函数就是f(m*n)=f(m)*f(n); 积性函数还有一个重要的性质就是积性函数的和也是积性函数。

可以证明gcd是积性函数,那么ans就是积性函数。根据积性函数的定义可以把n因式分解,考虑每个素因子的F函数

那么在n^0.5时间内可求

有一个问题:我的数组开太大了,虽然本地运行完全没问题,但是在BZOJ上提交后秒T。。。

后来又去POJ交才发现是MLE。。。。数组改小后两个都A了。

太坑了。比赛的时候一定要注意数组大小。一些老版本的编译器实在是不可依赖。。(NOIP2012就是这样,本来有20分的程序因为数组开大了就RE。本地同样没问题。。。)一定注意!!!!

View Code
 1 /************************************************************** 

 2     Problem: 2705 

 3     User: wsc500 

 4     Language: C++ 

 5     Result: Accepted 

 6     Time:12 ms 

 7     Memory:2912 kb 

 8 ****************************************************************/

 9   

10 #include <cstdio> 

11 #include <cstdlib> 

12 #include <iostream> 

13 #include <cmath> 

14 #include <cstring> 

15 #define MAXN 70000 

16 using namespace std; 

17 typedef long long LL; 

18 /*Gloable*/

19 LL p[MAXN],k[MAXN],pk[MAXN],t,n; 

20 /*Function*/

21 void Factorization(LL x){ 

22     for (LL i=2;i*i<=n;i++) if (x%i==0){ 

23         p[t]=i; 

24         pk[t]=1; 

25         while (x%i==0)  {pk[t]*=p[t]; k[t]++; x=x/i;} 

26         t++; 

27     } 

28     if (x!=1)   {p[t]=x; pk[t]=x; k[t]=1; t++;} 

29 } 

30 int main() 

31 { 

32     LL ans=1; 

33     cin>>n; 

34     Factorization(n); 

35   

36     for (LL i=0;i<t;i++){ 

37         ans*=pk[i]/p[i]*(p[i]*k[i]-k[i]+p[i]); 

38     } 

39   

40     cout<<ans<<endl; 

41     return 0; 

42 }

 

你可能感兴趣的:(long)