标签:题解 cf contest
【前言】咦?现在怎么流行打CF了?于是当一帮大爷在执着的打div 1的时候,我偷偷的在刷div 2。至于怎么决定场次嘛,一般我报一个数字A,随便再拉一个人选一个数字B。然后开始做第A^B场。如果觉得机密性不高,来点取模吧。然后今天做的这场少有的AK了。(其实模拟赛只做完了4题,最后1题来不及打了)
等等,话说前面几题不用写题解了?算了,让我难得风光一下啦。
【A】
这道题到底有什么意思呢?反正题目是模模糊糊的看懂的。好像是给定N个段和数K,你可以把某一段的L减一,把某一段的R加一,都算一次操作。最终要使得总长度%K=0,求最少操作次数。直接贴代码算了。
#include<cstdio>
using namespace std;
int n,k,i,ans,x,y;
int main()
{
scanf("%d%d",&n,&k);
for (i=1;i<=n;i++)
scanf("%d%d",&x,&y),ans+=y-x+1;
if (ans%k==0) puts("0");
else printf("%d",k-ans%k);
return 0;
}
【B】
Little penguin Polo has an n?×?m matrix, consisting of integers. Let‘s index the matrix rows from 1 to n from
top to bottom and let‘s index the columns from 1 to m from left to right. Let‘s represent the matrix element on the intersection of row i and
column j as aij.
In one move the penguin can add or subtract number d from some matrix element. Find the minimum number of moves needed to make all matrix elements equal.
If the described plan is impossible to carry out, say so.
Output
In a single line print a single integer — the minimum number of moves the penguin needs to make all matrix elements equal. If that is impossible, print "-1" (without
the quotes).
题意是给出N*M个带权方格,每次操作只能对每个格子+或-d。求把所有方块变成相同的权值最小操作次数,无解输出-1。判是否有解解很简单,只要权值A%d是否是定值,或者ΔA%d是否=0。如果有解的话一定是改成中位数。
#include<cstdio>
#include<algorithm>
using namespace std;
int a[100005],num,n,m,d,i,j,tot,ans;
int main()
{
scanf("%d%d%d",&n,&m,&d);
scanf("%d",&a[tot=1]);num=a[1]%d;
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
{
if (i==1&&j==1) continue;
scanf("%d",&a[++tot]);
if (a[tot]%d!=num) {puts("-1");return 0;}
}
sort(a+1,a+tot+1);
for (i=1;i<=tot;i++)
ans+=abs(a[i]-a[(tot+1)>>1])/d;
printf("%d",ans);
return 0;
}
【C】
Little penguin Polo adores strings. But most of all he adores strings of length n.
One day he wanted to find a string that meets the following conditions:
-
The string consists of n lowercase English letters (that is, the string‘s length equals n),
exactly k of these letters are distinct.
-
No two neighbouring letters of a string coincide; that is, if we represent a string as s?=?s1s2... sn,
then the following inequality holds,si?≠?si?+?1(1?≤?i?<?n).
-
Among all strings that meet points 1 and 2, the required string is lexicographically smallest.
Help him find such string or state that such string doesn‘t exist.
String x?=?x1x2... xp is lexicographically
less than string y?=?y1y2... yq,
if either p?<?q and x1?=?y1,?x2?=?y2,?...
,?xp?=?yp,
or there is such number r (r?<?p,?r?<?q),
that x1?=?y1,?x2?=?y2,?...
,?xr?=?yr and xr?+?1?<?yr?+?1.
The characters of the strings are compared by their ASCII codes.
Output
In a single line print the required string. If there isn‘t such string, print "-1" (without the quotes).
构造题。构造一个字典序最小的小写字符串,使得相邻两个字母不同,而且恰好只按顺序出现了K个字母。大概的想法就是前面一直a和b交替,后来K-2位一直沿着c,d,e放下去。
注意这道题是有cha点的。如果K=1,显然是无解,因为相邻两个不能相同。但是当N=1时还是正确的:‘a‘!
#include<cstdio>
#define PR ({puts("-1");return 0;})
using namespace std;
int n,i,m;
int main()
{
scanf("%d%d",&n,&m);
if (m==1&&n==1) {putchar('a');return 0;}
if (m>n||m==1) PR;
for (i=1;i<=n-(m-2);i++)
if (i&1) putchar('a');else putchar('b');
for (i=1;i<=m-2;i++) putchar((char)(i+98));
return 0;
}
【D】
开始还以为是DP,然后题意看了半天。大意是有N个房子,让你给每个房子加一个“索引”P,当你到了X后,你下一次去Px。再给定一个数K,对索引有下列三个要求:
①从1号点走出去后必须能回到1号点。
②从前K号点走出去后必须能回到1号点。(为什么觉得上面一个是多余的?)
③从K+1~N号点走出去后必须不能回到1号点。
求所有索引的方案取模10^9+7的值。
对于K+1~N号点,显然和1~K是隔绝的,因此方案数是简单的计算(N-K)^(N-K)。
对于1号点,显然它可以填K种索引。
对于2~K号点,开始我束手无策。后来发现K<=8!那么只要简单的dfs一下,再验证一下即可。
最后用乘法原理把三者乘起来。
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const LL P=1000000007ll;
int a[10],f[10],i;
LL num,ans,n,k;
int work(int k,int flag)
{
f[k]=flag;if (k==1) return 1;
if (f[a[k]]!=flag) return work(a[k],flag);
return 0;
}
inline void check()
{
int ok=1;memset(f,0,sizeof(f));
for (int i=2;i<=k&&ok;i++)
ok&=work(i,i);
if (ok) num++;
}
void dfs(int now)
{
if (now==k+1) {check();return;}
for (int i=1;i<=k;i++)
a[now]=i,dfs(now+1);
}
int main()
{
scanf("%I64d%I64d",&n,&k);ans=k;
for (i=1;i<=n-k;i++)
(ans*=(n-k))%=P;
dfs(2);
if (num) (ans*=num)%=P;
printf("%I64d",ans);
return 0;
}
【E】
Little penguin Polo likes permutations. But most of all he likes permutations of integers from 0 to n,
inclusive.
For permutation p?=?p0,?p1,?...,?pn,
Polo has defined its beauty — number .
Expression means
applying the operation of bitwise excluding "OR" to numbers x and y.
This operation exists in all modern programming languages, for example, in language C++ and Java it is represented as "^"
and in Pascal — as "xor".
Help him find among all permutations of integers from 0 to n the
permutation with the maximum beauty.
Output
In the first line print integer m the maximum possible beauty. In the second line print any permutation of integers from 0 to n with
the beauty equal to m.
If there are several suitable permutations, you are allowed to print any of them.
题意很清楚,求0~N的排列Ai,使得max{Σi^A[i]}。
开始以为是从大到小枚举i,在字母树中贪心地找与它尽量能匹配的。后来打表后发现是一一对应的,不用这么麻烦。如果i没有被匹配过,我们可以构造出k<i,且k和i匹配的值=k+i。然后扫一遍即可。
这里是打表程序:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,sum,t,now,ans,i,wri[10005][105],a[105];
int main()
{
freopen("1.txt","w",stdout);
for (n=3;n<=9;n++)
{
sum=1;int F=0;
for (i=0;i<=n;i++)
a[i]=i,sum*=(n+1-i);
ans=0;
for (t=1;t<=sum;t++)
{
now=0;
for (i=0;i<=n;i++)
now+=(i^a[i]);
if (now>ans)
ans=now,F=1,memcpy(wri[1],a,sizeof(a));
else if (now==ans) memcpy(wri[++F],a,sizeof(a));
next_permutation(a,a+n+1);
}
printf("%d %d\n",n,ans);
for (int j=1;j<=F;j++)
{
for (i=0;i<=n;i++) printf("%d ",wri[j][i]);
puts("");
}
puts("");
}
return 0;
}
这里是AC程序:
#include<cstdio>
#include<cmath>
using namespace std;
int a[25],f[1000005],x,k,i,n;long long ans=0;
int main()
{
scanf("%d",&n);
for (i=n;i;i--)
if (!f[i])
{
k=(int)(log2(i))+1;x=(1<<k)-1-i;
f[x]=1;a[i]=x;a[x]=i;ans+=(long long)((1<<k)-1)<<1;
}
printf("%I64d\n",ans);
for (i=0;i<=n;i++) printf("%d ",a[i]);
}
Codeforces Round #177 (Div. 2) 题解,布布扣,bubuko.com
Codeforces Round #177 (Div. 2) 题解
标签:题解 cf contest
原文地址:http://blog.csdn.net/jiangshibiao/article/details/37740461