《DP练习》

https://ac.nowcoder.com/acm/problem/21302:

注意到x % 3 = (x * 10) % 3.

因为(x * 10) % 3 = (x % 3) * (10 % 3) = x % 3 * 1 = x % 3.

所以对余数dp即可。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
const int N = 3e3 + 5;
const int M = 1e4 + 5;
const double eps = 1e-10;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e18
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {return (x + y) % Mod;}
inline long long DEC(long long x,long long y) {return (x - y + Mod) % Mod;}
inline long long MUL(long long x,long long y) {return x * y % Mod;}

string s;
LL dp[51][5];//dp[i][j] - 到第i个,余数为j
void solve() { 
    cin >> s;
    int n = s.size();
    for(int i = 1;i <= n;++i) {
        int x = s[i - 1] - '0';
        for(int j = 0;j < 3;++j) {
            dp[i][j] = ADD(dp[i][j],dp[i - 1][j]);
            dp[i][(j + x) % 3] = ADD(dp[i][(j + x) % 3],dp[i - 1][j]);
        }
        dp[i][x % 3] = ADD(dp[i][x % 3],1);
    }
    printf("%lld\n",dp[n][0]);
}   
int main() {
    solve();
  //  system("pause");
    return 0;
}
View Code

 https://ac.nowcoder.com/acm/problem/21303:

这题有点无语,题目说可以删(),我以为只能删连续的(),但是其实它是可以隔开的一对一对删。

也就是合法的匹配都可以删,那dp转移的时候利用括号匹配来判断一段能不能删去。

(PS:题解很多都是假的做法.

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
const int N = 3e3 + 5;
const int M = 1e4 + 5;
const double eps = 1e-10;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e18
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {return (x + y) % Mod;}
inline long long DEC(long long x,long long y) {return (x - y + Mod) % Mod;}
inline long long MUL(long long x,long long y) {return x * y % Mod;}

bool dp[105][105];//dp[i][j] - i,j完全匹配
string a,b;
bool check(int L,int r) {
    if((r - L + 1) % 2 != 0) return false;
    int cnt = 0;
    for(int i = L;i <= r;++i) {
        if(a[i - 1] == '(') cnt++;
        else {
            if(cnt == 0) return false;
            cnt--; 
        }
    }
    return cnt == 0;
}
void solve() { 
    cin >> a >> b;
    int n = a.size(),m = b.size();
    dp[0][0] = 1;
    for(int j = 1;j <= m;++j) {
        for(int i = 1;i <= n;++i) {
            if(a[i - 1] == b[j - 1]) {
                for(int k = 0;k < i;++k) {
                    if(dp[k][j - 1] && check(k + 1,i - 1)) dp[i][j] = 1;
                }
            }
        }
    }
    bool f = 0;
    for(int i = 1;i <= n;++i) {
        if(dp[i][m] && (check(i + 1,n) || i == n)) f = 1;
    }
    printf("%s\n",f ? "Possible" : "Impossible");
}   
int main() {
    solve();
    system("pause");
    return 0;
}
/*
(())()
()

()(())
(())
*/
View Code

https://atcoder.jp/contests/abc207/tasks/abc207_f:

似曾相识,这里只需要定义好状态就很好转移了,见代码。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 2e3 + 5;
const int M = 1e4 + 5;
const LL Mod = 1e9 + 7;
#define rep(at,am,as) for(int at = am;at <= as;++at)
#define ret(at,am,as) for(int at = am;at >= as;--at)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

LL dp[N][N][3],f[N][3],ans[N];//保护了j个点,0 - 没放置且没被覆盖,1 - 没放置被覆盖,2 - 放置
int n,sz[N];
vector<int> G[N];
void dfs(int u,int fa) {
    sz[u] = 1;
    dp[u][0][0] = 1;
    dp[u][1][2] = 1;
    for(auto v : G[u]) {
        if(v == fa) continue;
        dfs(v,u);
        memset(f,0,sizeof(f));
        for(int i = 0;i <= sz[u];++i) {
            for(int j = 0;j <= sz[v];++j) {
                f[i + j][0] = ADD(f[i + j][0],dp[u][i][0] * ADD(dp[v][j][0],dp[v][j][1]) % Mod);
                f[i + j + 1][1] = ADD(f[i + j + 1][1],dp[u][i][0] * dp[v][j][2] % Mod);
                f[i + j][1] = ADD(f[i + j][1],dp[u][i][1] * ADD(ADD(dp[v][j][0],dp[v][j][1]),dp[v][j][2]) % Mod);
                f[i + j + 1][2] = ADD(f[i + j + 1][2],dp[u][i][2] * dp[v][j][0] % Mod);
                f[i + j][2] = ADD(f[i + j][2],dp[u][i][2] * ADD(dp[v][j][1],dp[v][j][2]) % Mod);
            }
        }
        sz[u] += sz[v];
        for(int i = 0;i <= sz[u];++i) {
            for(int k = 0;k < 3;++k) {
                dp[u][i][k] = f[i][k];
            }
        }
    }
}
void solve() {
    scanf("%d",&n);
    rep(i,1,n - 1) {
        int u,v;scanf("%d %d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,0);
    for(int i = 0;i <= n;++i) {
        for(int k = 0;k < 3;++k) {
            ans[i] = ADD(ans[i],dp[1][i][k]);
        }
    }
    for(int i = 0;i <= n;++i) printf("%lld\n",ans[i]);
}   
int main() {
    //int _;
    //for(scanf("%d",&_);_;_--) {
        solve();
    //}
    system("pause");
    return 0;
}
View Code

 

posted @ 2021-10-22 09:25  levill  阅读(32)  评论(0编辑  收藏  举报