讨论 / 这是标程,那位大牛解释以下
181818181818 2012-02-29 21:40:00
点我顶贴 收藏 删除
const

prime :array [1..4] of Longint=(2,3,5,7);

var

a,c :array [0..100000] of Longint;

s :array [1..4,0..20] of Longint;

t :array [1..4] of Longint;

n,i,ans :Longint;

n1,n2 :Longint;

st :ansistring;

Procedure Getprime(n,p:Longint);

var

i,j,k :Longint;

begin

while n>1 do

begin

for i:=1 to 4 do

while n mod prime[i]=0 do

begin

inc(t[i],p);

n:=n div prime[i];

end;

n:=n mod 10;

end;

end;

Procedure GetC(n:Longint);

var

i,j,k :Longint;

begin

c[n]:=1;

for i:=1 to 4 do

begin

j:=0;

k:=t[i];

while k>0 do

begin

if k mod 2=1 then

c[n]:=(c[n]*s[i,j]) mod 10;

k:=k shr 1;

inc(j);

end;

end;

end;

Procedure Prepare;

var

i,j,k :Longint;

begin

for i:=1 to 4 do

begin

s[i,0]:=prime[i];

for j:=1 to 20 do

s[i,j]:=sqr(s[i,j-1]) mod 10;

end;

c[0]:=1;c[n-2]:=1;

for i:=1 to n shr 1 do

begin

Getprime(n-i-1,1);

Getprime(i,-1);

GetC(i);

c[n-i-2]:=c[i];

end;

end;

Begin

readln(st);

for i:=1 to length(st) do

if st[i] in [0..9] then

begin

inc(n);

a[n]:=ord(st[i])-ord(0);

end;

Prepare;

for i:=1 to n-1 do

n1:=(n1+a[i]*c[i-1]) mod 10;

for i:=2 to n do

n2:=(n2+a[i]*c[i-2]) mod 10;

ans:=n1*10+n2;

if ans=0 then ans:=100;

writeln(ans);

End.

我不希望看到这题的通过人数飙升

#1 wish@2008-05-09 20:06:00
回复 删除
这题本人想过很长时间

实质上是排列组合,求组合数

容易证明

结果第一位数与前面 n-1 个数字有关(设它们为 a1..an-1)

为 (a1 * C(n - 2, 1) + a2 * C(n - 2, 2) + a3 * C(n - 2, 3) ... + an-1 * C(n - 2, n - 1)) mod 10

但是 n 可能比较大(100000),直接公式求肯定超时

不过这题很特殊,它只要组合数的个位数,我于是就用分解因数来加速,最后好像8个点(比裸加多一个)。

一直没想到什么好的求组合数个位数的方法,研究此程序中~

#2 wish@2008-05-09 20:09:00
回复 删除
这个程序的 Prepare 肯定就是求组合数个位数字的函数,研究中~

我原来裸求过100000的组合数,发现了个位数字的确很有规律(中间很多 0,而且结果中有很多对称(回文)的重复。

但查阅很多资料都未果~

#3 我是天才他哥@2008-05-09 22:54:00
回复 删除
快意的。。。
#4 peterjiang@2008-07-27 01:33:00
回复 删除
wish 给出的公式错误

因该是

(a1 * C(n - 2, 0) + a2 * C(n - 2, 1) + a3 * C(n - 2, 2) ... + an-1 * C(n - 2, n - 2)) mod 10

#5 zjlsykw3636@2008-08-19 06:21:00
回复 删除
.........这题需要那么复杂么 = =|||
#6 DarkMaster@2008-08-19 06:24:00
回复 删除
搞不懂饿/。。
#7 格洋@2008-10-23 20:44:00
回复 删除
那个公式的反例是  6 1 2 4 3 5
#8 hades@2008-10-23 21:46:00
回复 删除
简单一点 发现

杨辉三角!!!!!

自己推

#9 格洋@2008-10-31 01:01:00
回复 删除
1 5 3 5 4 3

6 8 8 9 7

4 6 7 6

0 3 3

3 6

首先把数字放在格子的,第1行最后的3走到结果数字6(按题向下走一格向左走0或1格)需要走4行4列,这样它对结果数字个位的影响就是它走到6的方案数C(4,4),依次类推再找1行倒数第2个,结果中的个位就是(3*C(4,4)+4*C(4,3)+5*C(4,2)+3*C(4,1)+5*C(4,0))mod 10。依次类推算下面的吧!

#10 Mato完整版@2008-11-16 02:12:00
回复 删除
我发现,

结果的十位数:

(A(1)*C(n-1, 0)+A(2)*C(n-1, 1)+...+A(n-1)*C(n-1, n-2))MOD 10

结果的个位数:

(A(2)*C(n-1, 0)+A(3)*C(n-1, 1)+...+A(n)*C(n-1, n-2))MOD 10

求组合的公式:C(n, i)=C(n, i-1)*(n+1-i)DIV i

C(n, 0)=1

可是这里C(n, i)只能保留个位数,如果再按照这种方法计算的话会出问题!

怎么办?

查看更多回复
提交回复