hdu 5225 Tom and permutation && BestCoder Round #40

来源:互联网 发布:如何参观清华大学知乎 编辑:程序博客网 时间:2024/04/20 12:42

问题描述
Tom学会了通过写程序求出一个1-n的排列的逆序对数,但他的老师给了他一个难题:给出一个1-n的排列,求所有字典序比它小的1-n的排列的逆序对数之和。Tom一时不知道该怎么做,所以他来找你帮他解决这个问题。因为数可能很大,答案对109+7取模。
输入描述
输入包含多组数据(大约20组)。对于每一组数据,第一行一个正整数n,第二行n个数,是一个n的排列。n100
输出描述
对于每组数据输出一行,答案模109+7
输入样例
32 1 352 1 4 3 5
输出样例
175


题解:主要就是枚举,bc的题解写的很清楚

总结:

1.如果比赛中有道题目卡在一块了,应该赶紧看看其他题,缓解一下,避免进入死胡同

2.这次因为三重循环的变量写错了WA了好几次,貌似这种情况碰到很多遍了,以后再碰到三重循环的时候,写完简

单检查一遍还是比较有必要的


#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;typedef long long LL;#define MAXN 105const int MOD = 1e9 + 7;LL dp[MAXN],d[MAXN],s[MAXN],ans;int num[MAXN];int main(){    dp[0] = 1;    for(int i = 1;i < MAXN;i++)        dp[i] = (dp[i - 1] * i) % MOD;    for(int i = 2;i < MAXN;i++)        d[i] = ((i * d[i - 1]) % MOD + (dp[i - 1] * (i * (i - 1) / 2)) % MOD) % MOD;    int n;    while(scanf("%d",&n) != EOF)    {        for(int i = 0;i < n;i++)            scanf("%d",&num[i]);        for(int i = 1;i < n;i++)        {            s[i] = 0;            for(int j = 1;j < n;j++)                for(int k = 0;k < min(i,j);k++)                    if(num[k] > num[j])s[i]++;        }        ans = 0;        for(int i = n - 2;i >= 0;i--)        {            for(int j = i + 1;j < n;j++)            {                LL cur = 0;                if(num[i] > num[j])                {                    swap(num[i],num[j]);                    for(int k = i;k < n;k++)                    {                        if(num[i] > num[k])cur++;                    }                    ans = (ans + (s[i] + cur) * dp[n - i - 1] + d[n - i - 1]) % MOD;                    swap(num[i],num[j]);                }            }        }        printf("%I64d\n",ans);    }}




0 0
原创粉丝点击