公式推导:
当n是偶数,m是偶数的时候,举个例子 n=6,m=2时,我们画图表示:
我们看对称的时候没有重复出现的都是关于中心对称的,那么我们在加上不重复的再除以2不就是C(6,2)的答案吗,那么不重复的怎么求呢,n=6,m=2时,不重复的不就是左边的和对称的右边的一个的组合吗,那就是C(3,1)!
再想n =6,m=4时,那么我们按照上面的方式思考不重复的,就是中心对称的部分,那么就是
|(1,2),(5,6)|(1,3)(4,6)|(2,3),(4,5)|那就是左三个选两个和右边的对称就是C(3,2)!
一般情况,如果
1.n是偶数,m是偶数,那么就会有对称的C(n/2,m/2),就是左半对称区间选m/2个;
2.n是奇数,m是偶数,那么n是奇数,如果还满足对称关系也是很好办的那就中间的不要放在两边那就是和1一样,也是C(n/2,m/2),你可能问中间的呢,你没有删除呀,n/2自动下取整,正好出去中间部分哦!
3.n是奇数,m是奇数,那么满足中间对称,把m中的一个刚刚好放在正中间,m剩下的就是偶数,把问题变成了1,那么还是C(n/2,m/2)
4.n是偶数,m是奇数,这个我们就满足不了对称了,直接除以2即可;
综上:.n是偶数,m是奇数,Ans(n,m)=C(n,m)/2;
其余的就是:Ans(n,m)=(C(n/2,m/2)+C(n,m))/2;
最后上代码:
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include<bitset>
using namespace std;
#define int long long
const int N = 1e3 + 10;
const int INF=0x3f3f3f3f;
const long long LLINF=4e18+5;
typedef long long LL;
typedef pair<int, int> PII;
#define xx first
#define yy second
#define endl '\n'
struct node
{
// bool operator<(const node &a) const
// {
// }
};
void ClearFloat()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int read() {
int ret = 0, f = 1;
char ch = getchar();
while ('0' > ch || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while ('0' <= ch && ch <= '9') {
ret = ret * 10 + ch - '0';
ch = getchar();
}
return ret * f;
}
int n,m;
int a[N][N],c[N][N];
signed main()
{
ClearFloat();
cin>>n>>m;
//预处理
for(int i=0;i<=50;i++)
{
a[i][0]=1;
for(int j=1;j<=i;j++)
{
a[i][j]=a[i-1][j]+a[i-1][j-1];
}
}
for(int i=0;i<=50;i++)
{
for(int j=0;j<=i;j++)
{
if(i%2==0&&j%2==1)
{
c[i][j]=a[i][j]/2;
}
else
{
c[i][j]=(a[i][j]+a[i/2][j/2])/2;
}
}
}
int sum=0;
for(int i=0;i<=m/2;i++)
{
if(m-i<=n&&m-i>=0)
{
sum+=c[n][i]+c[n][m-i];
}
}
cout<<sum<<endl;
}