整理下当时写A的思路,有点混乱 导致花费了大量时间
- 题意 : 从n个数中选出k个(k<=n)使得其和的根=i 问有多少种选取方法
- 第一反应要组合数,然后容易发现gen(a+b)=gen(gen(a)+gen(b)),故先把所有输入全部转换为gen(a[i]);
- 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;
}