- 论坛徽章:
- 1
|
我得到的O(log(n))的程序:
- int fac2[] = {6,2,4,8};
- int facn[] = {6,6,2,6,4};
- long long cnt[30][4]={{1,1,3,0}}, cnt_len = 1;
- int co_list[30], list_len=0;
- int get_val(int v, int b, int k)
- {
- v = v * facn[b] * fac2[(k*b)%4] % 10;
- return v;
- }
- void preproc(long long n)
- {
- int k, i, j, mul;
- for(k=0; n>0; n/=5, k++) {
- co_list[k] = n%5;
- if(k >= cnt_len) {
- memset(cnt[k], 0, sizeof(long long)*4);
- for(j=0; j<5; j++) {
- mul = get_val(1, j, k);
- for(i=0; i<4; i++)
- cnt[k][((mul*2*(i+1))%10)/2-1] += cnt[k-1][i];
- }
- cnt_len++;
- }
- }
- list_len = k-1;
- }
- long long calc(long long n)
- {
- int i, j, k, mul = 1, v=1;
- long long val = 0, part[4];
- preproc(n);
- memset(part,0,sizeof(part));
- for(i=list_len; i>0; i--) {
- for(j=1; j<=co_list[i]; j++) {
- mul = get_val(v, j-1, i);
- for(k=0; k<4; k++) {
- part[((mul*2*(k+1))%10)/2-1] += cnt[i-1][k];
- }
- }
- v = get_val(v, j-1, i);
- }
- for(j=0; j<=co_list[0]; j++) {
- mul = get_val(v, j, 0);
- part[mul/2-1]++;
- }
- val += 2*part[0] + 4*part[1] + 6*part[2] + 8*part[3] - 11;
- return val;
- }
- int main()
- {
- long long n;
- while(1){
- printf("input n:");
- scanf("%lld", &n);
- if(n == 0) break;
- printf("result:%lld\n", calc(n));
- }
- }
复制代码
提示:
用f(n)表示n!的最右不为0的数字,则可以得到下面的公式:
设n=Ak*5^k+...+A1*5+A0(0<=Ai<=4)为其5进制展开
则f(n)=f(A0)f(A1)...f(Ak)*2^(A1+2A2+...+kAk)%10 |
评分
-
查看全部评分
|