https://codeforces.com/problemset/problem/553/A
dp+组合数学
dp[i] 放前i种颜色的方法数
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e3+7; const ll mod = 1e9+7; int a[N]; ll dp[N],f[N]; void work(){ f[0]=1; f[1]=1; for(int i=2;i<N;i++) f[i]=f[i-1]*i%mod; } ll q_pow(ll a,ll n){ ll ans=1; ll base=a; while(n){ if(n&1) ans=(ans*base)%mod; base=base*base%mod; n>>=1; } return ans; } ll inv(ll a,ll b){ return q_pow(a,b-2); } ll C(int n,int m){ return f[n]*inv(f[n-m]*f[m]%mod,mod)%mod; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int k; cin>>k; for(int i=1;i<=k;i++){ cin>>a[i]; } work(); int sum=a[1]; dp[1]=1; for(int i=2;i<=k;i++){ dp[i]=(dp[i-1]*C(sum+a[i]-1,a[i]-1))%mod; sum+=a[i]; } cout<<dp[k]<<endl; return 0; }
https://codeforces.com/problemset/problem/264/B
dp+简单数论
dp[i] 表示当前当前位置因子为i的所能构成的序列长度
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5+7; const ll mod = 1e9+7; int a[N]; int dp[N]; vector<int> v[N]; void work(){ for(int i=2;i<N;i++) for(int j=i;j<N;j+=i) v[j].push_back(i); } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin>>n; work(); for(int i=1;i<=n;i++) cin>>a[i]; v[1].push_back(1); for(int i=1;i<=n;i++){ int tmp=0; for(int j=0;j<v[a[i]].size();j++) tmp=max(tmp,dp[v[a[i]][j]]); for(int j=0;j<v[a[i]].size();j++) dp[v[a[i]][j]]=tmp+1; } int ans=0; for(int i=1;i<N;i++) ans=max(ans,dp[i]); cout<<ans<<endl; return 0; }
http://codeforces.com/contest/339/problem/C
dp+路径还原
dp[i][j] 表示用了j克的砝码 变成了重量为i 是否存在
#include <bits/stdc++.h> using namespace std; const double pi = acos(-1.0); const int N = 2e5+7; const int inf = 0x3f3f3f3f; const double eps = 1e-6; typedef long long ll; typedef pair<int,int> pii; const ll mod = 1e9+7; vector<int> w; int dp[207][15]; pii path[1007][207][15]; void find(int x,int y,int cnt){ if(cnt==0) return ; find(path[cnt][x][y].first,path[cnt][x][y].second,cnt-1); cout<<y<<" "; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); string s; cin>>s; for(int i=0;i<10;i++) if(s[i]=='1') w.push_back(i+1); int m; cin>>m; int fix=100; for(int i=0;i<w.size();i++){ dp[fix+w[i]][w[i]]=1; path[1][fix+w[i]][w[i]]=make_pair(fix,0); } for(int i=2;i<=m;i++){ if(i&1){ for(int j=fix-50;j<fix;j++) for(int k=0;k<w.size();k++) if(dp[j][w[k]]){ // cout<<j<<" "<<w[k]<<endl; for(int l=0;l<w.size();l++){ // cout<<j<<" "<<fix<<endl; if(w[l]==w[k]||j+w[l]<=fix) continue; dp[j+w[l]][w[l]]=1; path[i][j+w[l]][w[l]]=make_pair(j,w[k]); } dp[j][w[k]]=0; } }else{ // cout<<"11"<<endl; for(int j=fix+1;j<=fix+1+50;j++) for(int k=0;k<w.size();k++) if(dp[j][w[k]]){ // cout<<j<<" "<<w[k]<<endl; for(int l=0;l<w.size();l++){ if(w[l]==w[k]||j-w[l]>=fix) continue; dp[j-w[l]][w[l]]=1; // cout<<j-w[l]<<endl; path[i][j-w[l]][w[l]]=make_pair(j,w[k]); } dp[j][w[k]]=0; } } } if(m&1){ int x=-1,y=-1; for(int i=fix+1;i<fix+1+50;i++) for(int j=0;j<w.size();j++) if(dp[i][w[j]]){ x=i; y=w[j]; break; } if(x==-1){ cout<<"NO "; }else{ cout<<"YES "; // cout<<x<<" "<<y<<endl; find(x,y,m); cout<<" "; } }else{ int x=-1,y=-1; for(int i=fix-50;i<fix;i++) for(int j=0;j<w.size();j++) if(dp[i][w[j]]){ x=i; y=w[j]; break; } if(x==-1){ cout<<"NO "; }else{ cout<<"YES "; // cout<<x<<" "<<y<<endl; find(x,y,m); cout<<" "; } } return 0; }
https://codeforces.com/problemset/problem/977/F
dp+路径
dp[i]表示以i位置为结尾所能构成的最大连续个数 用一个map记录最后一个数为i的最大长度
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pi; const int N = 2e5+7; const ll mod = 1e9+7; int a[N],dp[N],path[N]; map<int,pi> mm; vector<int> v; void find(int x){ if(!x) return ; find(path[x]); v.push_back(x); } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=n;i++){ if(mm.count(a[i]-1)){ dp[i]=mm[a[i]-1].first+1; mm[a[i]]=make_pair(dp[i],i); path[i]=mm[a[i]-1].second; }else{ dp[i]=1; mm[a[i]]=make_pair(1,i); } } int ans=0; int xx; for(int i=1;i<=n;i++){ if(dp[i]>ans){ ans=dp[i]; xx=i; } } find(xx); cout<<ans<<" "; for(int i=0;i<v.size();i++) cout<<v[i]<<" "; cout<<" "; return 0; }
https://codeforces.com/problemset/problem/711/C
dp[i][j][k] 表示前i个位置 最后一个数颜色为j 且分为k组的最小花费
#include <bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const double eps = 1e-6; const int N = 4e5+7; typedef long long ll; const ll mod = 1e9+7; using namespace std; int a[107]; ll cost[107][107]; ll dp[107][107][107]; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n,m,k; cin>>n>>m>>k; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>cost[i][j]; memset(dp,0x3f3f3f3f3f3f3f3f,sizeof(dp)); for(int i=1;i<=n;i++){ for(int kk=1;kk<=k;kk++){ if(kk>i) break; if(a[i]){ if(i==1){ dp[i][a[i]][1]=0; continue; } dp[i][a[i]][kk]=dp[i-1][a[i]][kk]; for(int j=1;j<=m;j++){ if(j==a[i]) continue; dp[i][a[i]][kk]=min(dp[i][a[i]][kk],dp[i-1][j][kk-1]); } }else{ if(i==1){ for(int j=1;j<=m;j++) dp[i][j][1]=cost[1][j]; continue; } for(int j=1;j<=m;j++){ dp[i][j][kk]=dp[i-1][j][kk]+cost[i][j]; for(int l=1;l<=m;l++){ if(j==l) continue; dp[i][j][kk]=min(dp[i][j][kk],dp[i-1][l][kk-1]+cost[i][j]); } } } } } ll ans=0x3f3f3f3f3f3f3f3f; for(int i=1;i<=m;i++) ans=min(ans,dp[n][i][k]); if(ans==0x3f3f3f3f3f3f3f3f) cout<<"-1"<<endl; else cout<<ans<<endl; return 0; }
http://codeforces.com/problemset/problem/279/C
dp[i][j]表示当前升上去或者降下来的最左点
#include <bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const double eps = 1e-6; const int N = 1e5+7; typedef long long ll; const ll mod = 1e9+7; using namespace std; int a[N]; int dp[N][2]; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; dp[1][0]=1; dp[1][1]=1; for(int i=2;i<=n;i++){ if(a[i]<a[i-1]){ dp[i][0]=i; dp[i][1]=dp[i-1][1]; }else if(a[i]>a[i-1]){ dp[i][0]=dp[i-1][0]; dp[i][1]=i; }else{ dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]; } } for(int i=1;i<=m;i++){ int l,r; cin>>l>>r; if(l<min(dp[dp[r][1]][0],dp[r][0])){ cout<<"No "; }else{ cout<<"Yes "; } } return 0; }