据说是错排公式的扩展,叫做限位排列。递推公式如下:
![](https://img-my.csdn.net/uploads/201304/05/1365173795_1172.jpg)
但是因为对1000000007取了模,所以其中的除法不一定能除尽,当然在数学意义上是能够除尽的。可以用费马小定理去掉除法:
若P为质数,则 a^p = a mod P,即 a^(p-1) = 1 mod P。
但是这样一来式中会出现三项相乘,用long long计算是必须的,此外每乘一次要取模,否则long long也可能溢出。
这次是观赏了神奇的缩减行数的代码风格。。
#include <stdio.h>
#define Mod 1000000007
typedef unsigned long long ull;
unsigned int a[100001];
unsigned int exp(int a)
{
unsigned int n = Mod - 2;
ull x = a, r = 1;
for( ; n; n>>=1)
{
if(n & 1) r = r*x%Mod;
x = x*x%Mod;
}
return r%Mod;
}
int main()
{
a[0]=a[3]=1, a[1]=a[2]=0, a[4]=2;
for(int i=5; i<100001; ++i)
a[i]=(i*(i-2ull)%Mod*a[i-1]%Mod+(ull)i*a[i-2]%Mod+(i&1?4:-4))%Mod*exp(i-2)%Mod;
for(int j; ~scanf("%d",&j); printf("%u\n", a[j]));
return 0;
}