codeforces1132f

题意:应该是懂得,然后题解在代码里面,比较意识流,看看就好了

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。 cf1800-2200的dp 随笔 第1张
 1 /*
 2    这种题给n=500就一种很浓浓的区间dp风格啊。。。。。。。。。。。。
 3    首先我们 设 dp[l][r]为把l和r这个段的全部点都消去所用的最小操作
 4    给一个样例  babaca
 5    首先如果我们可以知道ai[l]==ai[r]的话我们可以通过合并的时候减少一次操作
 6    然后这居然就可以了。。。。。。。。。。。?????????
 7    倒是真的无法反驳啊
 8    首先肯定是要枚举断点的,枚举断点和-1
 9 
10    那就有一个问题,枚举断点后我们会存在一个情况,假如断点两端相等怎么办,你枚举到下一层
11    不就可以了吗?
12 
13 */
14 #include <algorithm>
15 #include <iostream>
16 #include <cstdio>
17 #include <cstring>
18 #include <cmath>
19 #include <bitset>
20 typedef long long ll;
21 using namespace std;
22 char sz[510];
23 int dp[510][510];
24 int len;
25 int main(){
26     scanf("%d",&len);
27     scanf("%s",sz+1);
28     for(int i=1;i<=len;i++) dp[i][i]=1;//这个要记得
29     for(int i=len;i>=1;i--){
30         for(int j=i+1;j<=len;j++){
31             dp[i][j]=(j-i+1);//这个初始化是最好的
32             //我们以段长初始化就保证不会犯错误
33             for(int k=i+1;k<=j;k++){
34                 if(sz[i]==sz[j]) dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k][j]-1);
35                 else dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k][j]);
36             }
37         }
38     }
39     cout<<dp[1][len]<<endl;
40     return 0;
41 }
View Code

 

codeforces1117d

给出一个错误代码,原因应该很显然

cf1800-2200的dp 随笔 第3张
 1 /*
 2    这题的状态转移方程还是挺好推的
 3    但是我们不止这样就结束了啊。。。。。。。。。。
 4    首先我们得到的状态转移方程是dp[i] = dp[i-1] + dp[i-m];
 5    dp[0]=0  1 到 m-1 dp[i]=1;
 6    dp[m] =2;
 7    如果继续变大的吧   dp[i] =dp[i-1] + dp[i-m];
 8    从 i==m+1算起
 9    要算  n-m次
10     构造的矩阵:
11     [1 1]  *  [dp[i-1]]   =  [dp[i]]
12     [1 0]     [dp[i-m]]      [dp[i-1]]
13     然后我们就可以得到要算n-m次
14     然后就乱搞了啊
15 */
16 #include <algorithm>
17 #include <iostream>
18 #include <cstdio>
19 #include <cstring>
20 #include <cmath>
21 #include <bitset>
22 typedef long long ll;
23 using namespace std;
24 const ll mod=1000000007;
25 ll n,m;
26 ll f[3][3];
27 ll ans[3];
28 ll tmp1[3];
29 ll tmp2[3][3];
30 
31 void init(){
32     f[1][1]=1;f[1][2]=1;
33     f[2][1]=1;f[2][2]=0;
34     ans[1]=2;ans[2]=1;
35 }
36 
37 void query(){
38      memset(tmp1,0,sizeof(tmp1));
39      for(int i=1;i<=2;i++){
40          for(int k=1;k<=2;k++){
41              tmp1[i]=(tmp1[i]+(f[i][k]*ans[k])%mod)%mod;
42          }
43      }
44      for(int i=1;i<=2;i++) ans[i]=tmp1[i];
45 }
46 
47 void mul(){
48     memset(tmp2,0,sizeof(tmp2));
49     for(int i=1;i<=2;i++){
50         for(int j=1;j<=2;j++){
51             for(int k=1;k<=2;k++){
52                 tmp2[i][j]=(tmp2[i][j]+(f[i][k]*f[k][j])%mod)%mod;
53             }
54         }
55     }
56     for(int i=1;i<=2;i++)
57         for(int j=1;j<=2;j++)
58             f[i][j]=tmp2[i][j];
59 }
60 
61 void fast_pow(ll t){
62     while(t){
63         if(t%2==1) query();
64         mul();
65         t/=2;
66     }
67 }
68 
69 int main(){
70     scanf("%lld%lld",&n,&m);
71     if(n<=m-1){
72         printf("1\n");
73     }else if(n==m){
74         printf("2\n");
75     }else{
76         init();
77         fast_pow(n-m);
78         printf("%lld\n",ans[1]%mod);
79     }
80     return 0;
81 }
View Code

 上面这个代码为什么是错误的呢

原因如下:我在变化过程中这种只能面对m==2的情况,变化几次后我的f【i-m】的值早就已经不对了。。。。。。。。。。

接下来是正确代码:

cf1800-2200的dp 随笔 第5张
 1 /*
 2    这题的状态转移方程还是挺好推的
 3    但是我们不止这样就结束了啊。。。。。。。。。。
 4    首先我们得到的状态转移方程是dp[i] = dp[i-1] + dp[i-m];
 5    dp[0]=0  1 到 m-1 dp[i]=1;
 6    dp[m] =2;
 7    如果继续变大的吧   dp[i] =dp[i-1] + dp[i-m]
 8     然后我们就可以得到要算n-m次
 9     然后就乱搞了啊
10 */
11 #include <algorithm>
12 #include <iostream>
13 #include <cstdio>
14 #include <cstring>
15 #include <cmath>
16 #include <bitset>
17 typedef long long ll;
18 using namespace std;
19 const ll mod=1000000007;
20 ll n,m;
21 ll f[110][110];
22 ll ans[110];
23 ll tmp1[110];
24 ll tmp2[110][110];
25 
26 void init(){
27     memset(f,0,sizeof(f));
28     f[1][1]=1;f[1][m]=1;
29     for(int i=2;i<=m;i++)  f[i][i-1]=1;
30     ans[1]=2;
31     for(int i=2;i<=m;i++) ans[i]=1;
32 }
33 
34 void query(){
35      memset(tmp1,0,sizeof(tmp1));
36      for(int i=1;i<=m;i++){
37          for(int k=1;k<=m;k++){
38              tmp1[i]=(tmp1[i]+(ans[k]*f[i][k])%mod)%mod;
39          }
40      }
41      for(int i=1;i<=m;i++) ans[i]=tmp1[i];
42 }
43 
44 void mul(){
45     memset(tmp2,0,sizeof(tmp2));
46     for(int i=1;i<=m;i++){
47         for(int j=1;j<=m;j++){
48             for(int k=1;k<=m;k++){
49                 tmp2[i][j]=(tmp2[i][j]+(f[i][k]*f[k][j])%mod)%mod;
50             }
51         }
52     }
53     for(int i=1;i<=m;i++)
54         for(int j=1;j<=m;j++)
55             f[i][j]=tmp2[i][j];
56 }
57 
58 void fast_pow(ll t){
59     while(t){
60         if(t%2==1) query();
61         mul();
62         t/=2;
63     }
64 }
65 
66 int main(){
67     scanf("%lld%lld",&n,&m);
68     if(n<=m-1){
69         printf("1\n");
70     }else if(n==m){
71         printf("2\n");
72     }else{
73         init();
74         fast_pow(n-m);
75         printf("%lld\n",ans[1]%mod);
76     }
77     return 0;
78 }
View Code

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄