哈尔滨理工大学软件学院ACM程序设计全国邀请赛【不断更新】
C:给定N和M,要求用N个数,这些数的和要能够覆盖1~M中的所有数,求这些数的方案总数
看到N和M最大200,猜想是打表,但是没想明白怎么搞:看到标程,一眼题
dp【i】【j】【k】:用i个数,这些数的和要能够覆盖1~M中的所有数,其中最大数是k
要求最后的答案ans=dp【n】【m】【1】+dp【n】【m】【2】+dp【n】【m】【3】+……+dp【n】【m】【m】
转移怎么想呢:
枚举可以取到的最大值,至少为k,最大为j+1,还要满足和不超过极限值200的条件
所以,全部可以提前打表预处理好的
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 2000000007
const int maxn=220;
LL dp[maxn][maxn][maxn],ans;
int T,n,m;
int main(){
memset(dp,0,sizeof(dp));
dp[1][1][1]=1;
for(int i=1;i<=200;i++)
for(int j=1;j<=200;j++)
for(int k=1;k<=200;k++){
if (dp[i][j][k]==0) continue;
for(int Max=k;Max+j<=200&&Max<j+2;Max++)
dp[i+1][j+Max][Max]=(dp[i+1][j+Max][Max]+dp[i][j][k])%mod;
}
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
ans=0;
for(int Max=1;Max<=m;Max++)
ans=(ans+dp[n][m][Max])%mod;
printf("%lld\n",ans);
}
return 0;
}
E:求有多少个连续区间里,全部是6
直接从前到后扫描一遍就好了,注意int和long long
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=2e5+50;
char s[maxn];
LL ans;
int T,n,num;
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%s",&n,s);
ans=0;num=0;
for(int i=0;i<n;i++){
if (s[i]=='6') num++;
else num=0;
ans+=num;
}
printf("%lld\n",ans);
}
return 0;
}
L题先给题目一个好评,再给自己一个中评,分析:
看到这种四个这么大的数字,而且还有非法的情况-1要判断,肯定是个构造题(想到了可怕的青岛B题魔方)这种题分析思路更重要吧,写出心路历程
首先,a3和a4比较重要,因为判断构造的形式
如果a3=a4,68686或者86868都可以
如果a3=a4+1,那么68要比86多一个,686868这样的
如果a4=a3+1,那么868686这样的
我们不能一直这样分类下去:在尝试无法构造其他的可能情况下,试图证明:
假设a3=a4+2,那么必须要出现6868这种的两个子段,那么用什么数字连接呢?
686866868和686886868,注意:这是可能的两种连接方式,但是,都会产生出来一个86!所以,不能出现a3>=a4+2的情况,同理对称的情况就不会出现了
总情况分类就是上面的三种:接下来需要数数,判断6和8的个数是不是可以满足至少的要求!
多的8是尽可能放在后面的,多的6是尽可能放在前面的(废话:因为要求数最小)
有了这些,分类打表就不难处理了
#include<bits/stdc++.h>
using namespace std;
int a1,a2,a3,a4;
int main(){
while(scanf("%d%d%d%d",&a1,&a2,&a3,&a4)!=EOF){
if (abs(a3-a4)>1) puts("-1");
else if (a3==a4){
if (a1>a3&&a2>=a3){
for(int i=1;i<=a1-a3;i++) printf("6");
for(int i=1;i<a3;i++) printf("86");
for(int i=1;i<=a2-a3;i++) printf("8");
puts("86");
}
else if (a1>=a3&&a2>a3){
printf("86");
for(int i=1;i<=a1-a3;i++) printf("6");
for(int i=1;i<a3;i++) printf("86");
for(int i=1;i<=a2-a3;i++) printf("8");
puts("");
}
else puts("-1");
}
else if (a3==a4+1){
if (a1>=a3&&a2>=a3){
for(int i=1;i<=a1-a3;i++) printf("6");
for(int i=1;i<=a3;i++) printf("68");
for(int i=1;i<=a2-a3;i++) printf("8");
puts("");
}
else puts("-1");
}
else if (a4==a3+1){
if (a1>=a4&&a2>=a4){
printf("86");
for(int i=1;i<=a1-a4;i++) printf("6");
for(int i=1;i<=a4-2;i++) printf("86");
for(int i=1;i<=a2-a4;i++) printf("8");
puts("86");
}
else puts("-1");
}
}
return 0;
}