链接:
http://codeforces.com/contest/554
比赛情况描述:
黑掉AB,手打C由于数组开小RE,赛后过了D。
A题水题。题意对于一个已知字符串,在任意位置插入一个字符,问最后可以得到多少种不同的新字符串。举例三个a,aa,ab即可出公式(n+1)*25+1;
B题思维题,题意给一个01矩阵,每次可以使某一列上的01翻转,问最多有多少全为1的行。因为初始状态决定不论如何翻转两个行都是不同或相同的状态,因此统计最多的初始状态相同的行个数输出即可。
C题dp。给定不同颜色球的个数,要求颜色数大的球的最后一个必须在比它颜色数小的最后一个球的后面,问最多有多少种方法。
自己的解法是:假设前i-1个的颜色已经弄好,且值为dp[i-1]。对于第i个颜色,第一 插在最后面,剩下的需要不重复的插在sum+1个空中。(sum为之前的球的总个数)。 这时候出现一种很牛逼的多叉树来统计这种不重复的插空情况。设lv[i][j]表示对于对于 第i个空的多叉树,深度为j时下面的叶子节点个数,多叉数的子节点只有小于等于它 自身的值。lv[i][0] = lv[i][1] = 1.lv[i][j] = lv[i-1][1]+lv[i-1][2]+...+lv[i-1][j];lv[1][j]=1; dp[i] = dp[i-1]*lv[sum+1][num_of_now-1];
然而C题一般是思维题:先涂颜色k,显然最后一个球肯定只能涂颜色k。然后前 面的n - 1个球随便选c[k] - 1个球涂上k颜色。这样涂并不影响其它球的涂法,因为 题目的限制只在最后一个球。所以我们就从每个颜色的最后一个球下手。然后再涂颜色 k - 1。既然颜色k涂完了,就不用管它了,剩下n - c[k]个未涂色的球,完全可以看成 是一排崭新的球去涂k - 1种颜色。所以实际上每个颜色的涂法之间并不干涉,是相互 独立的。因此用乘法原理即可解决。
所有球的总数不超过1000,直接预处理组合数即可。
(赛后)D题,图论找规律:
已知循环节只能长度为2或1。因为根据题意,对于一个循环节大数在前小数在后,假 设存在循环节大于2(如3)的情况,设ijk。则应有i>j>k,但是j所处位置必须要指 回k即i<j故可证。
对于每个长度n设可组成data[n]中情况,则假设第一个位置和第二位置不换和第一个 位置和第二个位置互换得到data[n] = data[n-1] + data[n-2],然后通过递归得到每个点 应不应该互换
源码:
A:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
char sss[20+5];
int main()
{
while(scanf("%s",sss) != EOF){
int res=0;
int n=strlen(sss);
res+=(n+1)*(26-n);
res+=n*n;
printf("%d\n",res);
}
return 0;
}
B题:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
#define gmax(a,b) a>b?a:b
//#define gmin(a,b) a<b?a:b
//typedef long long LL;
const int MAXN = 100+5;
int data[MAXN][MAXN];
char str[MAXN];
int n;
int main()
{
while(scanf("%d",&n) != EOF){
for(int i=0; i<n; i++){
scanf("%s",str);
for(int j=0; j<n; j++)
data[i][j] = str[j] - '0';
}
int res = 0;
for(int i=0; i<n; i++){
int tt = 0;
for(int j=0; j<n; j++){
int ff = 1;
for(int k=0; k<n; k++){
if(data[i][k] != data[j][k]){
ff = 0;
break;
}
}
tt += ff;
}
res = gmax(res, tt);
}
printf("%d\n",res);
}
return 0;
}
C题:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
#define gmax(a,b) a>b?a:b
#define gmin(a,b) a<b?a:b
typedef long long LL;
const LL MOD = 1e9+7;
const int MAXN = 1000+10;
int lv[MAXN];
LL dp[1000+5];
LL jia[1000+10][1000+10];
int n;
//int _pow(int a,int b)
//{
// if(b == 0)
// return 1;
// int tt = a;
// int ans = 0;
// while(b){
// if(b & 1)
// ans = (ans + tt) % MOD;
// tt = (tt*tt) % MOD;
// b = b>>1;
// }
// return ans;
//}
void init()
{
for(int i=0; i<=1000+5; i++){
int sum = 0;
for(int j=0; j<=1000+5; j++){
if(i==0)
jia[i][j] = 1;
else{
if(j <= 1)
sum = jia[i-1][j];
else
sum = (sum + jia[i-1][j]) % MOD;
jia[i][j] = sum;
}
}
}
}
int main()
{
init();
// for(int i=0; i<4; i++){
// for(int j=0; j<4; j++)
// printf("%d ",jia[i][j]);
// printf("\n");
// }
while(scanf("%d",&n) != EOF){
for(int i=1; i<=n; i++)
scanf("%d",&lv[i]);
memset(dp, 0, sizeof(dp));
LL pre,sum;
pre = sum = 0;
for(int i=1; i<=n; i++){
if(i == 1){
pre = sum = lv[i];
dp[1] = 1;
}
else{
// int tans = _pow(pre+1, lv[i]-1);
// dp[i] = (tans * dp[i-1]) % MOD;
// if(jia[pre+1][lv[i]-1] == 0)
// dp[i] = dp[i-1];
// else
int f1 = pre+1;
int f2 = lv[i]-1;
// printf("f1 = %d,f2 = %d\n",pre+1,lv[i]-1);
// printf("jia = %d\n",jia[pre+1][lv[i]-1]);
dp[i] = (jia[f2][f1] * dp[i-1]) % MOD;
sum = sum + lv[i];
pre = sum;
}
// printf("pre = %d,sum = %d,now dp max = %d\n",pre,sum,dp[i]);
}
printf("%I64d\n",dp[n]);
}
return 0;
}
D题:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
const int MAXN = 50+5;
using namespace std;
typedef long long LL;
#define gmax(a,b) a>b?a:b
#define gmin(a,b) a<b?a:b
LL lv[MAXN];
int t[MAXN];
void init()
{
lv[0] = lv[1] = 1;
for(int i=2; i<MAXN; i++)
lv[i] = lv[i-1] + lv[i-2];
}
int main()
{
init();
// for(int i=0; i<MAXN; i++)
// printf("%I64d ",lv[i]);
// printf("\n");
int n;
LL k;
while(scanf("%d%I64d",&n,&k) != EOF){
int cnt = 0;
int org = n;
for(int i=1; i<=n; i++){
if(k > lv[n-i]){
t[cnt++] = i+1;
t[cnt++] = i;
k -= lv[n-i];
i++;
}
else
t[cnt++] = i;
}
int ff = 1;
for(int i=0; i<cnt; i++){
if(ff) ff = 0;
else printf(" ");
printf("%d",t[i]);
}
printf("\n");
}
return 0;
}