整理下当时写A的思路,有点混乱 导致花费了大量时间

  1. 题意 : 从n个数中选出k个(k<=n)使得其和的根=i 问有多少种选取方法
  2. 第一反应要组合数,然后容易发现gen(a+b)=gen(gen(a)+gen(b)),故先把所有输入全部转换为gen(a[i]);
  3. n的大小大概复杂度很适合dp,来分析一下dp[i][j]————处理了长度i-1的前缀且前面方案中根为j的数量,我们要明确因为是选取,故在后后面的过程我们要不断更新前面根的种类数和数量 那就开始转移方程吧
	dp[i][j]=(dp[i][j]+dp[i-1][j])%mod//比赛时因为忘了这一步故耗费了1h+++...
    ll now = j+a[i];
    if(now>=10)now=1+now%10;
    dp[i][j+now]=(dp[i][j+now]+dp[i-1][j])%mod;

整体代码

using namespace std;
typedef long long ll;
const int N = 1e5+8;
const int mod = 998244353;
vector<ll>v;
map<ll,ll>mp;
ll t,n,m,a[N],sum[N],dp[N][10];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        ll now = 0;
        if(a[i]>=10){
            while(a[i]>=10){
                now = 0;
                while(a[i]){
                    now+=a[i]%10;
                    a[i]/=10;
                }
                a[i]=now;
            }
            a[i]=now;
        }
    }
    dp[0][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=9;j++){
            dp[i][j]=(dp[i][j]+dp[i-1][j])%mod;
            ll now = j+a[i];
            if(now>=10)now=1+now%10;
            dp[i][now]=(dp[i][now]+dp[i-1][j])%mod;
        }
        dp[i][a[i]]=(dp[i][a[i]]+1)%mod;
    }
    for(int i=1;i<=9;i++){
        cout<<dp[n][i]<<' ';
    }
    return 0;
}