题目链接

https://ac.nowcoder.com/acm/contest/7412/I

解题思路

我的思路:

建立set容器dp[i][j],存储的是位于(i,j)时所有不同的权值和。
访问到(i,j)位置时,遍历(i-1,j)位置所有不同的权值和,再遍历(i,j-1)位置的权值和,把他俩位置中的权值和逐个与(i,j)位置的权值相加取模并insert进dp[i][j]中。
我代码运行时间比较短的原因在于 if(dp[i][j].size()>=mod){cout<<mod<<endl;return 0;},含义为如果在循环到(n,m)位置之前已经有某个位置所含的不同权值和个数比1e4+7大了,说明后面无论怎么加,怎么变,只要是由这个权值和个数大于1e4+7的位置转移过去的,必然个数都为1e4+7,而(n,m)位置必然由(i,j)转移得到,所以直接输出并return即可。(自认为灵魂所在!QWQ)

大佬思路:

dp[i][j][k]为bool数组,为1表示(i,j)位置权值和为k的情况存在,为0表示不存在。
枚举余数情况。
最终答案为dp[n][m][k],k从0到mod-1遍历累加。
注意:bool数组,不是bool开不下

我的AC代码

//我的代码运行时间比较短
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e4+7;
const int N=105;
set<int> dp[N][N];
ll a[N][N];
int n,m;
int read(){
    int x=0,f=1;
    char ch;
    ch=getchar();
    while(ch<'0' || ch>'9') {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9') {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int main(){
    n=read();
    m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            a[i][j]=read()%mod;
    for(int i=1;i<=n;i++) dp[i][0].insert(0);
    for(int j=1;j<=m;j++) dp[0][j].insert(0);
    dp[1][1].insert(a[1][1]);
    for(int i=1;i<=n;i++)    
        for(int j=1;j<=m;j++){
            if(i!=1)
                for(set<int>::iterator it=dp[i-1][j].begin();it!=dp[i-1][j].end();it++)
                    dp[i][j].insert((*it+a[i][j])%mod);
            if(j!=1)
                for(set<int>::iterator it=dp[i][j-1].begin();it!=dp[i][j-1].end();it++)
                    dp[i][j].insert((*it+a[i][j])%mod);
            if(dp[i][j].size()>=mod){cout<<mod<<endl;return 0;}
        }
    cout<<dp[n][m].size()<<endl;
} 

大佬AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e4+7;
const int N=110;
bool dp[N][N][11000];//bool!!!
int a[N][N];
int ans;
int n,m;
int read(){
    int x=0,f=1;
    char ch;
    ch=getchar();
    while(ch<'0' || ch>'9') {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9') {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int main(){
    n=read();
    m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            a[i][j]=read()%mod;

    dp[1][1][a[1][1]]=1;
    for(int i=1;i<=n;i++)    
        for(int j=1;j<=m;j++){
            if(i==1&&j==1) continue;
            for(int k=0;k<mod;k++){
                dp[i][j][(a[i][j]+k)%mod] |= dp[i-1][j][k];
                dp[i][j][(a[i][j]+k)%mod] |= dp[i][j-1][k];
            }
        }


    for(int k=0;k<mod;k++)
        ans+=dp[n][m][k];
    cout<<ans<<endl;
}