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 }