またcoutにやられた。
http://codeforces.com/contest/546/problem/D
問題
A,BからなるクエリがT個与えられる。
A!/B!を2以上の数で何回割ることができるか求めよ。
解法
Ω(x)をxの重複を含めた素因数の個数とする。
各クエリはΩ(A!)-Ω(B!)を求めればよい。
A≦5000000なので、先にΩ(x!)を5000000まで列挙しておけば、各クエリO(1)で終わる。
Ω(x!)=Ω(x) + Ω((x-1)!)より、Ω(x)を列挙すればΩ(x!)も容易に求められる。
問題はクエリ数が10^6と多いこと。
cout-endlをこの回数繰り返すとTLEするので、endlを避けたりprintfにする対応が必要。
int T; ll A,B; const int prime_max = 5200000; int NP,prime[1100000],divp[prime_max]; ll num[5050500]; ll sum[5050500]; void cprime() { for(int i=2;i<prime_max;i++) if(divp[i]==0) { for(int j=i*2;j>i&&j<prime_max;j+=i) divp[j]=i; } } void solve() { int i,j,k,l,r,x,y; string s; cprime(); for(i=2;i<=5000000;i++) { if(divp[i]==0) num[i]=1; else num[i]=num[i/divp[i]]+1; sum[i] = sum[i-1]+num[i]; } cin>>T; while(T--) { cin>>A>>B; _P("%d\n",(int)(sum[A]-sum[B])); } }
まとめ
10^5はまだしも、10^6の出力はendlを使っていはいけないことは覚えておかなくては。