这题是一道比较反常的dp逆向思维解决问题的题。

刚开始思路局限于对逆元的处理,当视野不再放在逆元之后,把样例拿来模拟了一番突然发现了解题的关键。我们会发现,第一个样例和第二个样例如果可以通过模拟的手段解决,那么本题就找到了解决的方法。

对于样例,我们发现11有且只能被西瓜质量为22组成,进而推广,假设前面均为00,那么第一个出现的数字必然是一个西瓜劈成两半的结果。因为西瓜的数目控制在了1e31e3,因此不可能出现0但是有1e9+71e9+7个西瓜。依照此法,我们发现,接下来的解决方案依然是一个dp,也就是记录下个数,然后使用背包方案,每次的背包方案与原先比较,如果不为00,那么就是有新的一半的西瓜产生。

以下为代码实现

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+7;
long long  dp[maxn];
long long ks[maxn];
const int mod = 1e9+7;
int main(){
    int n ,m;
    cin >> m;
    for(int i = 1 ; i<= m ; i++){
        cin>>dp[i];
    }
    dp[0] = 1;
    ks[0] = 1;
    vector<int>ve;
    for(int i = 1 ; i<=m ;i++){
        //这里记录下当前数值是否存在西瓜
        int tmp = (dp[i] - ks[i] + mod)%mod;
        for(int j = 1; j<=(dp[i] - ks[i] + mod)% mod;j++){
            ve.push_back(i*2);
        }

        //这里承担了背包记忆方案的作用
        while(tmp--){
         for(int k = m ; k>=0 ; k--){
            ks[k] += ks[k - i];
            ks[k] += ks[k - i*2];
            ks[k] %=mod;
          }
        }
         
    }
    cout<<ve.size()<<"\n";
    for(auto k : ve)cout<<k<<" ";
}