PKU已经挂了6天了,一直想验证自己写的logn的计算n!最后一位的算法是否正确,这次USACO告诉我我写对了!
USER: A e [chenh193]
TASK: fact4
LANG: C++
Compiling...
Compile: OK
Executing...
Test 1: TEST OK [0.000 secs, 4000 KB]
Test 2: TEST OK [0.022 secs, 4000 KB]
Test 3: TEST OK [0.000 secs, 3996 KB]
Test 4: TEST OK [0.011 secs, 3996 KB]
Test 5: TEST OK [0.011 secs, 3996 KB]
Test 6: TEST OK [0.011 secs, 4000 KB]
Test 7: TEST OK [0.011 secs, 3996 KB]
Test 8: TEST OK [0.000 secs, 4000 KB]
Test 9: TEST OK [0.011 secs, 4000 KB]
Test 10: TEST OK [0.000 secs, 4000 KB]
All tests OK.
int cnt2,cnt5,dir[]={1,1,3,1};
int ODD(int L,int R)
{
//1,3,5,7,9....
if(L>=R)return 1;
int Len=(R-L)/2+1;//长
int O_R=R,O_L=L,buf=1;
while(!(O_L%5==0&&O_L%2)&&O_L<=R)O_L++;
while(!(O_R%5==0&&O_R%2)&&O_R>=L)O_R--;
if(O_L<=O_R)
{
cnt5+=(O_R-O_L)/10+1;
buf*=ODD(O_L/5,O_R/5);
Len-=(O_R-O_L)/10+1;
}
buf*=((Len/4)&0x1?9:1);
buf*=dir[Len%4];
buf%=10;
return buf;
}
int nozero(int L,int R)//L*(L+1)*...*(R-1)*R的非0最后尾数
{
//分奇,偶
if(L>=R)return 1;
int O_L=L,O_R=R,buf=1,Len=R-L+1;
O_L+=(O_L&0X1);
O_R-=(O_R&0X1);
cnt2+=(O_R-O_L)/2+1;//该序列中的偶数的个数,需要继续讨论...
Len-=(O_R-O_L)/2+1;
buf*=nozero(O_L/2,O_R/2);//计算子集...
buf%=10;
//剩下的只可能是1,3,5,7,9结尾的数...
//去掉能被5整除的数...
O_L=L;O_R=R;
while(!(O_L%5==0&&O_L%2)&&O_L<=R)O_L++;
while(!(O_R%5==0&&O_R%2)&&O_R>=L)O_R--;
if(O_L<=O_R)
{
cnt5+=(O_R-O_L)/10+1;
Len-=(O_R-O_L)/10+1;
buf*=ODD(O_L/5,O_R/5);
}
buf*=((Len/4)&0x1?9:1);
buf*=dir[Len%4];
buf%=10;
return buf;
}
int main()
{
int N;
freopen("fact4.out","w",stdout);
freopen("fact4.in","r",stdin);
while(scanf("%d",&N)!=EOF)
{
cnt2=cnt5=0;
N=nozero(1,N);
N*=pmod(2,cnt2-cnt5,10);
printf("%d/n",N%10);
}
return 0;
}