写在前面,这场比赛是这个暑假最后一场多校比赛了,打得很不好,特别是在杭电的比赛,总是感觉水土不服一样。感觉自己比赛的时候总喜欢看榜,怎么说呢,看榜有看榜的好处吧,但是感觉在牛客和杭电的几场比赛都被榜带偏了,赛后补题的时候我觉得这题我是可以做出来的。说这么多,关键还是自己的比赛时的心态有问题,别一天天的盯着榜看,我觉得以后也要改正一下比赛时看榜的习惯了(或者说以后坚决不看榜),会做的总会做,不会做的看一辈子还是那样。
Mine Sweeper
题意:给出一个数s,构造出一个类似于扫雷游戏那种的矩阵,使得矩阵中所有数字之和为s。
思路:这题其实比赛时的思路已经很接近了,只是还是想复杂了一些,与官方题解的思路想到过一样的,但很快就想当然的否决了。这个题目其实如果用wps的表格进行模拟的话我觉得效果会更好。首先,当s<25的时候,我们就可以构造出X.X.X.X.类似这种的一行的矩阵出来,当s>25的时候,我们先这样考虑,对于一个完整的九宫格的话,我们只要在中心位置加上一个X,就相当于造成了增加8的贡献,
即使最大到1000的话我们也只需要125个这样的九宫格。如果构造完整的25X25的矩阵的话,那么就可以构造出12X12=144个这种的九宫格,这显然是够的,所以我们就看输入的s中有几个8,然后就构造出几个九宫格就行了,对于余数的情况,我们只要适当的添加一些X进去就行了。最后我们可以证明到不管s为多少我们都有最终的答案。
对于余数的情况,只要看代码,然后再用wps表格验证一下就行了,其实方法有很多。
代码:
#include<bits/stdc++.h>
using namespace std;
char c[30][30];
char b[30];
int s;
void deal1(){
for(int i=1;i<=25;i++){
if(i&1) b[i]='X';
else b[i]='.';
}
cout<<"1 "<<s+1<<endl;
for(int i=1;i<=s+1;i++){
cout<<b[i];
}
cout<<endl;
}
void deal2(){
int k1=s/8;
int k2=s%8;
int x=2,y=2;
while(k1>0){
c[x][y]='X';
y+=2;
if(y>24){
x+=2;
y=2;
}
k1--;
}
//对余数进行处理
if(k2==1) c[1][1]='X';
if(k2==2) c[1][1]=c[1][2]='X';
if(k2==3) c[1][2]='X';
if(k2==4) c[2][3]='X';
if(k2==5) c[1][1]=c[2][3]='X';
if(k2==6) c[25][25]=c[25][24]='X';
if(k2==7) c[1][1]=c[25][25]=c[25][24]='X';
cout<<"25 25"<<endl;
for(int i=1;i<=25;i++){
for(int j=1;j<=25;j++){
cout<<c[i][j];
}
cout<<endl;
}
}
int main(){
int t;
cin>>t;
while(t--){
for(int i=1;i<=25;i++){
for(int j=1;j<=25;j++){
c[i][j]='.';
}
}
cin>>s;
if(s<25){
deal1();
}
else deal2();
}
return 0;
}Permutation Counting
题意:这题有点cf的味道,给你一个长为n-1的01序列,表示的是1-n这n个数的某种排列,如果,那么第i个位置就是0,否则就是1,要求求出符合条件的构造情况有多少种?
思路:看了题解后还是一头雾水,怎么想到的这种的构造方法的?
可能是目前能力还没达到那种高度吧,把题解先贴在这里,希望以后能回来搞懂。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll res;
int a[5010];
ll dp[5010][5010];
void solve(){
int n;
cin>>n;
for(int i=1;i<n;i++) cin>>a[i];
memset(dp,0,sizeof(dp));
dp[1][1]=1;
if(a[1]) dp[2][1]=1;
else dp[2][2]=1;
for(int i=2;i<n;i++){
if(a[i]){
for(int j=i;j;j--){
dp[i+1][j]=(dp[i+1][j+1]+dp[i][j])%mod;
}
}
else{
for(int j=2;j<=i+1;j++){
dp[i+1][j]=(dp[i][j-1]+dp[i+1][j-1])%mod;
}
}
}
res=0;
for(int i=1;i<=n;i++) res=(res+dp[n][i])%mod;
cout<<res<<endl;
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}Task Scheduler
题意:最开始开的就是这道题目,我觉得这道题目才是签到题,但后面看榜的时候发现这道题目过的人不多,以为有什么大坑,在加上题目有点没搞懂什么意思。所以跑去开其他题了,后面队友又在开这道题我就没看了。。。
这题就是有n个任务,每个任务需要ti名工人去做,其中有m个工人,这m个工人之中又有k个工人是与这种任务无关的,(也就是只有m-k个工人派去做任务才有用)。然后要求求出n个任务的一种完成顺序,使得派遣工人的次数最少。题目保证工人的完成人数是够的,也就是肯定存在一种方案使得可以完成所有的工作。同时答案要保证序列的字典序最小。
思路:贪心。首先,我们先考虑k=0的情况,这种是有点难想到的,如果k=0的话,我们直接输出1-n即可,如果k!=0的话,我们为了选工人的时候能够提高完成任务的概率(有可能选了比较多的k个无关工人中的人),我们肯定是要确保在选人尽量选到有关的工人,所以我们只需要对每个任务所需要的工人的数量进行排序,从多到少进行分配即可。因为在分式当中,当分子比分母小的情况下,分母和分子减少相同数的情况下,分数的大小会变得更小。也就是越到后面,就难选到有关的工人,而你如果选的越多的话,就更难选到满足任务所需的工人了。
#include<bits/stdc++.h>
using namespace std;
struct node{
int val;
int index;
}Node[110];
bool cmp(node a,node b){
if(a.val!=b.val) return a.val>b.val;
return a.index<b.index;
}
void solve(){
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
cin>>Node[i].val;
Node[i].index=i;
}
if(k) sort(Node+1,Node+1+n,cmp);
for(int i=1;i<=n;i++){
cout<<Node[i].index;
if(i<n) cout<<" ";
}
cout<<endl;
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
京公网安备 11010502036488号