刚开始,写小范围暴力,试图找规律,顺便学习了一下next_permutation()
(1) int 类型的next_permutation
int main()
{
a[0]=1;a[1]=2;a[2]=3;
{
cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
} while (next_permutation(a,a+3)); //参数3指的是要进行排列的长度
//如果存在a之后的排列,就返回true。如果a是最后一个排列没有后继,返回false,每执行一次,a就变成它的后继
}
输出:
本题的暴力小范围程序(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;
}