思路:
一个算式肯定是加法和乘法交替的。假设乘法被分成个连续的段,加法被分成个连续的段,那么一定有。当时只想到了对每组连续的加法,如果元素不完全相同,那么运算的结果就会不同。正确的想法是:对于每组连续的加法或者乘法,如果组内的元素是相同的,那么运算的结果也是一样的。于是可以考虑将乘法分成或个连续的段、加法分成或个连续的段,那么答案就是。s2表示第二类斯特林数。
当时,会被计算两次,表示是下面的两种情况:A表示连续的加法,B表示连续的乘法
{ABAB} {BABA}
code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7; ll s2[3005][3005],fact[3005]; inline void pre() { fact[0]=1; s2[0][0]=1; for(int i=1; i<=3001; ++i) { s2[i][0]=0; s2[i][i]=1; fact[i]=(fact[i-1]*i)%mod; } for(int i=1; i<=3001; ++i) for(int j=1; j<=3001; ++j) s2[i][j]=(s2[i-1][j]*j+s2[i-1][j-1])%mod; } signed main() { int T,n,m,_min; pre(); cin>>T; while(T--) { cin>>n>>m; ll ans=1; _min=min(n,m); for(int i=1; i<=_min; ++i) { ans+=(s2[n][i]*fact[i]%mod+s2[n][i+1]*fact[i+1]%mod) *(s2[m][i]*fact[i]%mod+s2[m][i+1]*fact[i+1]%mod); ans%=mod; } cout<<ans<<'\n'; } return 0; }
递推,巨慢:
int fun(int n, int m) { if(n<m) return 0; else if(m == 0) return 0; else if(n == m) return 1; else return m*fun(n-1,m) + fun(n-1, m-1); }