[数论][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 }

 

posted @ 2013-04-03 13:05  wsc500  阅读(378)  评论(0编辑  收藏  举报