思路:

一个算式肯定是加法和乘法交替的。假设乘法被分成个连续的段,加法被分成个连续的段,那么一定有。当时只想到了对每组连续的加法,如果元素不完全相同,那么运算的结果就会不同。正确的想法是:对于每组连续的加法或者乘法,如果组内的元素是相同的,那么运算的结果也是一样的。于是可以考虑将乘法分成个连续的段、加法分成个连续的段,那么答案就是。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);
}