标题:出栈次序
X星球特别讲究秩序,所有道路都是单行线。一个甲壳虫车队,共16辆车,按照编号先后发车,夹在其它车流中,缓缓前行。
路边有个死胡同,只能容一辆车通过,是临时的检查站,如图【p1.png】所示。
X星球太死板,要求每辆路过的车必须进入检查站,也可能不检查就放行,也可能仔细检查。
如果车辆进入检查站和离开的次序可以任意交错。那么,该车队再次上路后,可能的次序有多少种?
为了方便起见,假设检查站可容纳任意数量的汽车。
显然,如果车队只有1辆车,可能次序1种;2辆车可能次序2种;3辆车可能次序5种。
现在足足有16辆车啊,亲!需要你计算出可能次序的数目。
这是一个整数,请通过浏览器提交答案,不要填写任何多余的内容(比如说明性文字)。
模拟:
// 7s
#include<bits/stdc++.h>
using namespace std;
struct node{
int l,r;
node(){};
node(int l_,int r_)
{
l=l_;
r=r_;
}
};
int main()
{
queue<node> q;
q.push(node(16,0));
node now;
int ans=0;
while(!q.empty())
{
now=q.front();
q.pop();
if(now.l==0 && now.r==0)
{
ans++;
continue;
}
if(now.l) q.push(node(now.l-1,now.r+1));
if(now.r) q.push(node(now.l,now.r-1));
}
cout<<ans<<endl;
return 0;
}
卡特兰数:
#include<bits/stdc++.h>
using namespace std;
int dp[22];
int main()
{
dp[0]=1;dp[1]=1;
for(int i=2;i<=16;i++)
{
for(int j=0;j<i;j++)
dp[i]+=dp[j]*dp[i-1-j];
// cout<<dp[i]<<endl;
}
cout<<dp[16]<<endl;
return 0;
}
标题:生物芯片
X博士正在研究一种生物芯片,其逻辑密集度、容量都远远高于普通的半导体芯片。
博士在芯片中设计了 n 个微型光源,每个光源操作一次就会改变其状态,即:点亮转为关闭,或关闭转为点亮。
这些光源的编号从 1 到 n,开始的时候所有光源都是关闭的。
博士计划在芯片上执行如下动作:
所有编号为2的倍数的光源操作一次,也就是把 2 4 6 8 ... 等序号光源打开
所有编号为3的倍数的光源操作一次, 也就是对 3 6 9 ... 等序号光源操作,注意此时6号光源又关闭了。
所有编号为4的倍数的光源操作一次。
.....
直到编号为 n 的倍数的光源操作一次。
X博士想知道:经过这些操作后,某个区间中的哪些光源是点亮的。
【输入格式】
3个用空格分开的整数:N L R (L<R<N<10^15) N表示光源数,L表示区间的左边界,R表示区间的右边界。
【输出格式】
输出1个整数,表示经过所有操作后,[L,R] 区间中有多少个光源是点亮的。
例如:
输入:
5 2 3
程序应该输出:
2
再例如:
输入:
10 3 6
程序应该输出:
3
因子数个数为奇数的去掉:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,l,r;
int main()
{
scanf("%lld%lld%lld",&n,&l,&r);
printf("%lld\n",r-l+1-((ll)sqrt(r*1.0)-(ll)sqrt(l*1.0-1)));
return 0;
}
标题:稍大的串
串可以按照字典序进行比较。例如:
abcd 小于 abdc
如果给定一个串,打乱组成它的字母,重新排列,可以得到许多不同的串,在这些不同的串中,有一个串刚好给定的串稍微大一些。科学地说:它是大于已知串的所有串中最小的串。你的任务就是求出这个“稍大的串”。
例如:
输入串:
abfxy
程序应该输出:
abfyx
再例如:
输入串:
ayyyxxff
程序应该输出:
fafxxyyy
数据规模约定:
输入的串不超过1000个字符。
特例:
如果已知的串已经是所有重组串中最大的,则原样输出读入的那个串。
从后往前,后面比当前大的:
#include<bits/stdc++.h>
using namespace std;
char s[1100];
int num[28];
int main()
{
scanf("%s",s);
int len=strlen(s);
int flag=0;
int id;
for(int i=len-1;i>=0;i--)
{
id=s[i]-'a';
num[id]++;
for(int j=id+1;j<=25;j++)
{
if(num[j])
{
for(int k=0;k<i;k++)
printf("%c",s[k]);
printf("%c",j+'a');
num[j]--;
for(int k=0;k<=25;k++)
{
while(num[k])
{
num[k]--;
printf("%c",k+'a');
}
}
printf("\n");
return 0;
}
}
}
printf("%s",s);
return 0;
}
标题:殖民地
带着殖民扩张的野心,Pear和他的星际舰队登上X星球的某平原。为了评估这块土地的潜在价值,Pear把它划分成了M*N格,每个格子上用一个整数(可正可负)表示它的价值。
Pear要做的事很简单——选择一些格子,占领这些土地,通过建立围栏把它们和其它土地隔开。对于M*N的格子,一共有(M+1)*N+M*(N+1)条围栏,即每个格子都有上下左右四个围栏;不在边界上的围栏被相邻的两个格子公用。大概如下图【p1.png】所示。
图中,蓝色的一段是围栏,属于格子1和2;红色的一段是围栏,属于格子3和4。
每个格子有一个可正可负的收益,而建围栏的代价则一定是正的。
你需要选择一些格子,然后选择一些围栏把它们围起来,使得所有选择的格子和所有没被选的格子严格的被隔开。选择的格子可以不连通,也可以有“洞”,即一个连通块中间有一些格子没选。注意,若中间有“洞”,那么根据定义,“洞”和连通块也必须被隔开。
Pear的目标很明确,花最小的代价,获得最大的收益。
【输入数据】
输入第一行两个正整数M N,表示行数和列数。
接下来M行,每行N个整数,构成矩阵A,A[i,j]表示第i行第j列格子的价值。
接下来M+1行,每行N个整数,构成矩阵B,B[i,j]表示第i行第j列上方的围栏建立代价。
特别的,B[M+1,j]表示第M行第j列下方的围栏建立代价。
接下来M行,每行N+1个整数,构成矩阵C,C[i,j]表示第i行第j列左方的围栏建立代价。
特别的,C[i,N+1]表示第i行第N列右方的围栏建立代价。
【输出数据】
一行。只有一个正整数,表示最大收益。
【输入样例1】
3 3
65 -6 -11
15 65 32
-8 5 66
4 1 6
7 3 11
23 21 22
5 25 22
26 1 1 13
16 3 3 4
6 3 1 2
程序应当输出:
123
【输入样例2】
6 6
72 2 -7 1 43 -12
74 74 -14 35 5 3
31 71 -12 70 38 66
40 -6 8 52 3 78
50 11 62 20 -6 61
76 55 67 28 -19 68
25 4 5 8 30 5
9 20 29 20 6 18
3 19 20 11 5 15
10 3 19 23 6 24
27 8 16 10 5 22
28 14 1 5 1 24
2 13 15 17 23 28
24 11 27 16 12 13 27
19 15 21 6 21 11 5
2 3 1 11 10 20 9
8 28 1 21 9 5 7
16 20 26 2 22 5 12
30 27 16 26 9 6 23
程序应当输出
870
【数据范围】
对于20%的数据,M,N<=4
对于50%的数据,M,N<=15
对于100%的数据,M,N<=200
A、B、C数组(所有的涉及到的格子、围栏输入数据)绝对值均不超过1000。根据题意,A数组可正可负,B、C数组均为正整数。
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms
目前我只会数据为小于10的情况,正解是最小割,待更新
数据<=10的状压dp:
// n * 2^m * 2^m * m
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int n,m,k;
int dp[15][1<<15];
int c[15][15],c1[15][15],c2[15][15];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&c[i][j]);
for(int i=0;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&c1[i][j]);
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
scanf("%d",&c2[i][j]);
memset(dp,-INF,sizeof(dp));
k=1<<m;
int cnt;
dp[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<k;j++) // down
{
for(int l=0;l<k;l++) // up
{
if(dp[i-1][l]==-INF) continue;
cnt=dp[i-1][l];
for(int p=1;p<=m;p++)
{
if((j&(1<<(p-1))) == 0) continue;
cnt+=c[i][p];
if(p==1)
{
cnt-=(c2[i][0]+c1[i][p]); // 左 下
if(l&(1<<(p-1))) // 上
cnt+=c1[i-1][p];
else
cnt-=c1[i-1][p];
if((j&(1<<p))==0) // 右
cnt-=c2[i][p];
}
else
{
cnt-=c1[i][p]; // 下
if(l&(1<<(p-1))) // 上
cnt+=c1[i-1][p];
else
cnt-=c1[i-1][p];
if((j&(1<<p)) == 0) // 右
cnt-=c2[i][p];
if((j&(1<<(p-2))) == 0) // 左
cnt-=c2[i][p-1];
}
}
dp[i][j]=max(dp[i][j],cnt);
}
}
}
int ans=0;
for(int i=0;i<k;i++) ans=max(dp[n][i],ans);
printf("%d\n",ans);
return 0;
}