[NOIP2017模拟]permut

xiaoxiao2021-02-28  105

题目: 求由1到n一共n个数组成的所有数列中,逆序对个数为k的有多少个。

输入格式: 第一行为一个整数T,为数据组数。 以下T行,每行两个整数n,k,意义如题目所述。

输出格式: 对每组数据输出答案对10000取模后的结果。

样例数据 输入 1 4 1 输出 3

数据范围: 对于30%的数据,满足n<=12 对于所有数据,满足n<=1000,k<=1000,T<=10

分析:刚看到这道题第一反应是,完了,归并排序不熟,然后发现这给了这么多组,绝不是归并那么简单,考虑到从小到大每加进去一个数,这个数是最大的,放最后逆序对数不变,向前移几个,逆序对加几,很快想到dp,但是,在给负数取模的时候出错了,见代码中注释。

100分代码:

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> #include<queue> #include<set> using namespace std; long long f[1010][1010],a[1010][1010]; int n[20],k[20],r,T; int getint() { int sum=0,f=1; char ch; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') { f=-1; ch=getchar(); } for(;ch>='0'&&ch<='9';ch=getchar()) sum=(sum<<3)+(sum<<1)+ch-48; return sum*f; } int main() { freopen("permut.in","r",stdin); freopen("permut.out","w",stdout); T=getint(); for(int i=1;i<=T;++i) { n[i]=getint();k[i]=getint(); r=max(r,n[i]); } f[2][1]=1; for(int i=2;i<=r;++i) f[i][0]=1; for(int i=3;i<=r;++i) { for(int j=1;j<=1000;++j) { if(j-i+1<=0) f[i][j]=(f[i][j]%10000+f[i][j-1]%10000+f[i-1][j]%10000)%10000; else f[i][j]=((f[i][j]+f[i][j-1]+f[i-1][j]-f[i-1][j-i])%10000+10000)%10000;//在这里,要减去一个数,有可能前两个正数取模之后很小,而要减的数取模后依然很大,就出现了负数,需要加上10000再000保险 } } for(int i=1;i<=T;++i) printf("%I64d\n",f[n[i]][k[i]]); return 0; }

本题结。

转载请注明原文地址: https://www.6miu.com/read-67278.html

最新回复(0)