题意:找出两个字符串最短的公共子字符串
分析:水题,最短一定是1,直接找一个一样的输出就行了。
代码:
#include
using namespace std;
int ji[1005];
int a[1005];
int b[1005];
void rlmn()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=0;i<=1000;i++)
ji[i]=0;
for (int i=0;i
水题,看题看了五分钟才确定真的这么水,被上场自闭场打怕了。
题意:
给出一堆石子,两个人去选,只能在目前的第一堆中拿任意数量。求最后谁赢。
分析:这题稍微想了一会。第一,如果在一开始的第一堆石子中出现了1,那么主动权就会易手。后面一样,只要有1就会不停的易手,直到第一个不是1的石子堆出现,就一切都能控制了。后面的1不会产生任何影响,只要每次给对面留一个,然后在1的前一堆一次性全拿走逼他拿1.
因此找到不是1的石子堆的时候,这时候谁取谁就赢。而从第一堆开始每出现一个1就会易手一次。
特殊情况:全是1,不会有不是1的石子堆。但是也最简单,直接按奇数偶数输出就行了。
代码:
#include
using namespace std;
int a[100005];
void rlmn()
{
int n;
int ans=0;
scanf("%d",&n);
for (int i=0;i
C1和C2是一样的题目,就是C2的n的数据范围从C1的1000变成了100000.因为我方法都是O(n)的,所以直接上C2的题了
题意:
先定义一个操作,叫做前缀处理。就是选取字符串的一些前缀,然后把前缀先全部异或,再反转过来。比如001011做前缀3操作,则先变成110011再变成011011.如果做前缀6就是先变成110100,再变成001011.
分析:
你相信我真的是水题啊。我觉得这是最简单的一题。他不需要你给出最短的解,只要能成功就行了啊。
所以你知道A通过x1x2x3...xn变成了B,那么B可以通过xnxn-1...x2x1变成A。然后就好办了啊,你把两个字符串全部变成11111...11111(就是全部1的形式)然后正序输出第一个变化的,反序输出第二个变化的,就行了。
所以怎么变成11111...11111形式呢?只要你确保前k个数一样,然后反转就没用了,反转前后都一样。所以只异或,就是1变0,0变1.所以你只要按位处理,第k位如果和第k+1位不一样,就做一次前缀k,这样第k位就和第k+1位一样了。然后继续往后知道n-2位。第n位只要判断一下是不是0,如果是0再进行前缀n操作就行了。这样两个字符串就可以很轻松的变成11111...11111形式,问题就迎刃而解了。
代码:
#include
using namespace std;
string s1,s2;
int ji1[100005];
int ji2[100005];
void rlmn()
{
int n;
scanf("%d",&n);
cin>>s1;
cin>>s2;
int flag1=0;
for (int i=0;i=0;i--)
{
printf(" %d",ji2[i]);
}
printf("\n");
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
rlmn();
}
}
当我发现c2所谓hard其实就是n大了一些我很惊喜啊,直接复制粘贴上去结果re了。
因为一开始数组开的是1005...内存不够。。。
题意:定义操作merge为:每次从两个数组里面选小的第一个放进merge后的数组。然后给你一个2n数的排列,问能不能找出两个n长度的数组正好merge成它。是就YES,否则就NO
分析:水题啊!我忘记了0-1背包怎么写,找了40分钟板子,就差10分钟(赛后5分钟debug完成,但是longlong忘记用lld了要t一发)
首先我们找原来的数组,找出所有的极值段。极值段的定义是,第一个数比后面的数都大。让每个极值段都尽量长。
比如2314分成(2)(3,1)(4)
32615784分成(32)(615)(7)(84)
这样做的原因是极值段一定是某一个n长度数组的一部分。
然后问题来了,虽然我将它分成了好几段,比如32615784变成了4段,长度分别是2312,但是我怎么知道能不能分成两半呢?
问题转化成,给出n个数,问能不能从中选取一些数,和正好是m。
一开始想的是暴力回溯,直接打死。因为数据量再1e3,所以我尽量往O(n2)的算法想,想了半小时想出了01背包。只是这个01背包很特殊,就是物品的重量和体积是一样大的,背包的空间就是n。然后必须恰好装满,还要将dp初始化负无穷。
考虑到数也不小,因此开了longlong,然后将初始化负无穷定义位-2143000000
这样如果背包最后价值大于0说明恰好实现(而且价值应该也是n)。否则说明实现不了。
代码:
#include
using namespace std;
typedef long long ll;
const int N=4015;
ll ji[N];
ll shu[N];
ll qu[N];
ll dp[N];
void rlmn()
{
ll n;
scanf("%lld",&n);
for (ll i=0;i<2*n;i++)
{
scanf("%lld",&shu[i]);
}
for (ll i=0;i<=2*n;i++)
{
ji[i]=0;
qu[i]=0;
dp[i]=-2143000000;
}
ll shumax=2*n;
for (ll i=2*n-1;i>=0;i--)
{
if (shu[i]!=shumax)
{
ji[shumax]++;
ji[shu[i]]=-1;//变成儿子了
}
else
{
ji[shu[i]]++;
shumax--;
while (ji[shumax]==-1)
{
shumax--;
}
}
}
ll num=1;
for (ll i=0;i<=2*n;i++)
{
if (ji[i]>0)
{
qu[num++]=ji[i];
}
}
num--;
ll V=n;
dp[0]=0;
//解决一个0-1背包
for (ll i=1;i<=num;i++)
{
for (ll j=V;j>=qu[i];j--)
{
dp[j]=max(dp[j],dp[j-qu[i]]+qu[i]);
}
}
if (dp[V]>0)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
rlmn();
}
}
本场比赛做出了4题。手速快点实际上五题也没问题。哎,不过无所谓,相当于要多打一场,多做一题最多到1400.下场上青!
不知道啥时候能打个蓝色哈。
赛中做了四题
赛后把本来应该做出来的补了
得到一个教训:如果开了longlong输入%d是会t的!