bzoj1925(next_permutation的第一次运用,难dp)

来源:互联网 发布:知乎的赞有什么用 编辑:程序博客网 时间:2024/05/16 10:23

刚开始,写小范围暴力,试图找规律,顺便学习了一下next_permutation()

(1) int 类型的next_permutation
 
int main()
{
 int a[3];
a[0]=1;a[1]=2;a[2]=3;
 do
{
cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
} while (next_permutation(a,a+3)); //参数3指的是要进行排列的长度
 
//如果存在a之后的排列,就返回true。如果a是最后一个排列没有后继,返回false,每执行一次,a就变成它的后继
 
 
}
 
输出:
 
 1 2 3
 1 3 2
 2 1 3
 2 3 1
 3 1 2
 3 2 1


本题的暴力小范围程序(by     next_permutatoin)

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;typedef long long ll;int a[36];void work(int n){for (int i=1;i<=n;i++) a[i]=i;ll ans=0;do{bool o,oo=true;if (a[2]<a[1]) o=true;else o=false;for (int i=2;i<n;i++){if (o){if (i&1) {if (a[i-1]<a[i]&&a[i+1]<a[i]) continue;oo=false;}else {if (a[i-1]>a[i]&&a[i+1]>a[i]) continue;oo=false;}}else {if (i&1){if (a[i-1]>a[i]&&a[i+1]>a[i]) continue;oo=false;}else {if (a[i-1]<a[i]&&a[i+1]<a[i]) continue;oo=false;}}}if (oo) ans++;}while (next_permutation(a+1,a+n+1));printf("%d = %d \n",n,ans); }int main(){freopen("debug.txt","w",stdout);for (int i=1;i<=20;i++){work(i);}return 0;}


标准做法:


这题写到一半,就发现自己错了。。由此还是要学会,怀疑的眼光审视自己的方法


需要滚动数组

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<cstdlib>using namespace std;typedef long long ll;int n;ll p,f[2][4205];int main(){scanf("%d%lld",&n,&p);int last=0,now=1;f[0][2]=1;for (int i=3;i<=n+1;i++){for (int j=1;j<=i;j++)f[now][j]=(f[now][j-1]+f[last][i-j+1])%p;swap(last,now);}printf("%lld",f[last][n+1]*2%p);return 0;}




0 0
原创粉丝点击