2、Tavan
描述
小 Zeljko 一直在阁楼里读他奶奶的旧信, 并且发现了一个长度为 N 的单词 。
不幸的是,由于溢出的墨水,他不知道单词的内容。他把看不清的 M 个字母每个字母都用一个字符'#' 替换后,在一张纸上重写了这个词。他把那张纸递给了他的奶奶 , 对于每个看不清的字母 , 奶奶给了他 K 个不同的可能 。 在那之后 ,Zeljko 在笔记本中写下了所有可能的单词,并决定仔细查看他们的属性,以确定原始单词是什么。在看到笔记本上写下的单词后,他的奶奶意识到他们正在
寻找的是按字典序排列的第 X 个单词。Zeljko 在他们学校学习字母表的那天生
病了,所以他要求你帮助他确定原来的单词。
输入
第一行输入包含整数 N,M ,K 和 X (1 ≤N ≤ 500,1 ≤ M ≤N ,1 ≤K ≤ 26,1 ≤X ≤)。分别表示单词的长度,看不清的字母数量,奶奶给出的字母的数量和原单词是字典序的第几个。
第二行输入包含一个长度为 N 的字符串,由小写英文字母和字符' #' 组成 。
表示 Zeljko 找到的单词,其中字符'#' 表示看不清的字母。
接下来 M 行中的每一行包含一个长度为 K 的字符串, 由 K 个不同的小写英文
字母组成。第 2+i 行的 K 个字母表示第 i i 个看不清的字母的K种可能。
保证 X 总是小于等于能构造出的单词的总数。
输出
输出一个字符串。表示原本的单词。
分数分布
对于 30% 的数据,M=1 并且 K=3 。
对于另外 30% 的数据, M=1 。
样例输入 1
9 2 3 7
po#olje#i
sol
znu
样例输出 1
posoljeni
样例输入 2
4 1 2 2
#rak
zm
样例输出 2
zrak
思路
之前用类似于递归的方法做错了只得了60分,后来改的时候就用循环代替实现
其实就是以k值和m值为基础的方案数的寻找
错误代码(又臭又长又耗时还错)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 501
int n,m,k,x,t;
long long p[MAXN]={1};
char c[MAXN],s[MAXN][27],w[MAXN];
bool cmp(char a,char b)
{
return int(a)<int(b);
}
void dfs(int h)
{
if(h>m)return;
for(int i=0;i<k;i++)
if(x<=p[m-h])
{
w[++t]=s[h][i];
dfs(h+1);
return;
}
else
x-=p[m-h];
}
int main()
{
freopen("tavan.in","r",stdin);
freopen("tavan.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&k,&x);
scanf("%s",c);
for(int i=1;i<=m;i++)
{
scanf("%s",s[i]);
sort(s[i],s[i]+k,cmp);
}
for(int i=1;i<=m;i++)
p[i]=k*p[i-1];
dfs(1);
t=1;
for(int i=0;i<n;i++)
if(c[i]=='#')
printf("%c",w[t++]);
else
printf("%c",c[i]);
}
正确代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 501
int n,m,k,x;
char c[MAXN],s[MAXN][27],w[MAXN];
int main()
{
freopen("tavan.in","r",stdin);
freopen("tavan.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&k,&x);
scanf("%s",c+1);
for(int i=1;i<=m;i++)
{
scanf("%s",s[i]);
sort(s[i],s[i]+k);
}
x--;//s序号从0开始
for(int i=n,j=m;i>=1;i--)//倒着除从最后往前找
if(c[i]=='#')
{
c[i]=s[j][x%k];//找到每层对应的序数
x/=k;
j--;
}
printf("%s",c+1);
}
3、Nizin
描述 Do Geese See God ?或者,Was It A Rat I Saw ?没关系,这只是展示 Mislav
对回文的热爱的不必要的介绍。帮他解决以下任务!设 A 是 N 个整数构成的数组 。 我们说 A 是回文 , 如果 A[i]=A[N-i+1] 对于每个 i 都成立,其中 A[i] 表示数组 A 的第 i 个元素,并且数组中的第一个元素编号是 1 。
Mislav 可以通过以下方式修改数组:在一次操作中,他选择该数组的两个
相邻元素并用它们的和替换它们。注意, 每次操作后数组中元素的数量将减少 1。
Mislav 想知道为了让数组变为回文的,他必须做出最少多少次操作。
输入
第一行输入包含整数 N (1 ≤N ≤ ),表示数组中的元素个数。
第二行输入包含 N 个用空格分隔的正整数,表示 Mislav 数组中的元素。数
组中的数字最多为 。
输出
输出一个整数。表示 Mislav 要把数组变为回文所需的最少操作次数。
分数分布
对于 30% 的数据, N ≤ 10 。
对于 60% 的数据, N ≤ 1000 。
样例输入 1
3
1 2 3
样例输出 1
1
样例输入 2
5
1 2 4 6 1
样例输出 2
1
样例输入 2
4
1 4 3 2
样例输出 2
2
思路
这道题过得蛮顺的,就从两端开始相等不变,小的加,最后大不了成一个数
代码
#include<cstdio>
#define MAXN 1000001
int n,ans;
int a[MAXN];
void wow(int s,int e)
{
if((s+1==e||s+2==e)&&a[s]==a[e])return;//中间有一个数也没关系
if(s==e)return;//这个就证明加到一块了
if(a[s]==a[e])
{
wow(s+1,e-1);
return;
}
else
{
if(a[s]<a[e])
{
ans++;
a[s+1]+=a[s];
wow(s+1,e);
return;
}
else
{
ans++;
a[e-1]+=a[e];
wow(s,e-1);
return;
}
}
}
int main()
{
freopen("nizin.in","r",stdin);
freopen("nizin.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
wow(1,n);
printf("%d",ans);
}
4、Prosjecni
描述
Slavko 很无聊,所以他把正整数填到 N*N 的方阵中。
如果他填出来的方阵满足以下条件,他会特别高兴:
● 每行中的数字的平均值是一个位于同一行的整数。
● 每列中的数字的平均值是一个位于同一列的整数。
● 表中的所有数字都不同。
帮助 Slavko 找到一种会让他开心的填法。
输入
第一行输入包含整数 N (1 ≤N ≤ 100 )。表示方阵的行数和列数。
输出
输出 N行,每行输出 N 个由空格分隔的整数 . 令第 i行中的第 j 个数字对应
于Slavko 将在方阵的第 i 行第 j列写下的值。
所有数字必须大于 0 且小于。
如果有多个解决方案,则输出任意一个。
如果没有任何解决方案,则输出 -1 。
分数分布
无特殊分数分布。
样例输入 1
3
样例输出 1
1 2 3
4 5 6
7 8 9
样例输入 2
2
样例输出 2
-1
思路
这道题我一开始想的就是找规律,可是规律找错了(>﹏<)
没关系,正确规律是:
1、当n=2时,无解
2、当n为奇数时,直接1~n*n输出
3、当n为偶数时,1行的最后一个n*(n-1)/2,1~n-1行在上一行的基础上+n*(n-1)/2,最后一行以每一列的最后一个为平均数求最后一行的数
代码
#include<cstdio>
int n;
int a[101][101];
int main()
{
freopen("prosjecni.in","r",stdin);
freopen("prosjecni.out","w",stdout);
scanf("%d",&n);
if(n==2)
printf("-1");
else
{
if(n%2==1)
{
int x=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<n;j++)
printf("%d ",x++);
printf("%d\n",x++);
}
}
else
{
for(int i=1;i<n;i++)
a[n][i]=a[1][i]=i;
a[n][n]=a[1][n]=(n-1)*n/2;
for(int i=2;i<n;i++)
for(int j=1;j<=n;j++)
{
a[i][j]=a[i-1][j]+n*(n-1)/2;
a[n][j]+=a[i][j];
}
for(int i=1;i<=n;i++)
{
a[n][i]=a[n-1][i]*n-a[n][i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<n;j++)
printf("%d ",a[i][j]);
printf("%d\n",a[i][n]);
}
}
}
}