POJ 3761 Bubble Sort 题目链接:http://poj.org/problem?id=3761
题目大意:要用冒泡排序给一个长度为n的数列排序(n给出,无重复元素),问恰好k次排好的原排列个数有多少种。
题目分析:网上的解释总感觉不大全,我就把我卡住的地方着重说一下吧。给出了n和k后,可以把数组分成两个部分,上k个数和下n-k个数。上k个数怎么排也不可能达到k个逆序数了,所以暂时忽略它们的顺序,将它们随意摆放后开始把下n-k个数向其中插,这样做可以得到幂的算法(因为每次插入一个数后对下一个数没有影响[更大的数必须排在更小的数右边,不然逆序数可能会出现大于k的])。这种计算幂的方法可以帮我们得到逆序数是Σ(从1~m的),而我们需要逆序数是k的,那么就可以计算1~k和1~(k-1)的,一减就是结果。
code:
#include<stdio.h>
#define MOD 20100713
#define K 1000010
int fac[K];
void init()
{
fac[0]=1;
for(long long i=1;i<K;i++)
{
fac[i]=(i*fac[i-1])%MOD;
}
}
long long quickPow(long long a,long long b)
{
if(b==0)return 1;
if(b==1)return a;
long long t=quickPow(a,b/2);
t=(t*t)%MOD;
if(b&1)return (t*a)%MOD;
else return t;
}
long long solve(int n,int k)
{
long long res=fac[k]*(quickPow(k+1,n-k)-quickPow(k,n-k))%MOD;
if(res<0)return res+MOD;
else return res;
}
int main()
{
int tt,n,k;
scanf("%d",&tt);
init();
while(tt--)
{
scanf("%d%d",&n,&k);
printf("%lld\n",solve(n,k));
}
return 0;
}
PS:老师给讲的这题,讲的很清楚,过了一天自己也差不多能推出来。最大的收获在于见识了一道较复杂题的推理过程,其次就是学习了快速幂的算法,二分思想果然屡试不爽…也差点被自己弄崩溃了,边界一百万写成了十万居然白交了十四遍没有发现…
PSS:参考过这一篇http://www.cnblogs.com/Wizmann/archive/2012/05/12/2496860.html