Description
windy学会了一种游戏。对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应。最开始windy把数字按顺序1,2,3,……,N写一排在纸上。然后再在这一排下面写上它们对应的数字。然后又在新的一排下面写上它们对应的数字。如此反复,直到序列再次变为1,2,3,……,N。 如: 1 2 3 4 5 6 对应的关系为 1->2 2->3 3->1 4->5 5->4 6->6 windy的操作如下 1 2 3 4 5 6 2 3 1 5 4 6 3 1 2 4 5 6 1 2 3 5 4 6 2 3 1 4 5 6 3 1 2 5 4 6 1 2 3 4 5 6 这时,我们就有若干排1到N的排列,上例中有7排。现在windy想知道,对于所有可能的对应关系,有多少种可能的排数。
Input
包含一个整数,N。
Output
包含一个整数,可能的排数。
Sample Input
【输入样例一】
3
【输入样例二】
10
Sample Output
【输出样例一】
3
【输出样例二】
16
【数据规模和约定】
30%的数据,满足 1 <= N <= 10 。
100%的数据,满足 1 <= N <= 1000 。
我傻叉了,写完WA了半天,然后反应过来,哦,他是在求最小公倍数啊(没有看清题目就乱搞........最开始还以为是乘积的个数)
先筛素数,然后枚举每个因子选几次方,然后减去这个数的几次方,枚举下一个质数
用记忆化搜索很好写
1 const 2 maxn=1010; 3 var 4 n,tot:longint; 5 flag:array[0..maxn]of boolean; 6 zhi:array[0..maxn]of longint; 7 f:array[0..maxn,0..maxn]of int64; 8 9 procedure shai; 10 var 11 i,j:longint; 12 begin 13 for i:=2 to n do 14 begin 15 if flag[i]=false then 16 begin 17 inc(tot); 18 zhi[tot]:=i; 19 end; 20 for j:=1 to tot do 21 begin 22 if zhi[j]*i>n then break; 23 flag[zhi[j]*i]:=true; 24 if i mod zhi[j]=0 then break; 25 end; 26 end; 27 end; 28 29 function fx(x,a:longint):int64; 30 var 31 i,s:longint; 32 begin 33 if f[x,a]>0 then exit(f[x,a]); 34 fx:=0; 35 if zhi[x]>a then exit(1); 36 if x>tot then exit(1); 37 s:=1; 38 inc(fx,fx(x+1,a)); 39 for i:=1 to a div zhi[x] do 40 begin 41 s:=s*zhi[x]; 42 if s>a then break; 43 inc(fx,fx(x+1,a-s)); 44 end; 45 f[x,a]:=fx; 46 end; 47 48 begin 49 read(n); 50 shai; 51 write(fx(1,n)); 52 end.