五一期间,怎么能闲着,好久都没打大型个人赛了,来一场找找感觉
总的难度感觉还可以,最终六题收场,海星
A Red Rover
思路:其实这题可能在刚开场的时候,给人一种签到题的感觉,由于排在第一个,大家一起拼命过题,导致ac数直线上升,然而,就我个人而言,刚看到这题的时候确实没什么太多思路,只是最终看到过题数较多重回来思考才成功在终场前过掉了这一题
然后,现在整理来看,思路也是很清晰的,由于串长只有100,果断O(n^2)暴力,对于每一个子串,贪心取第一个,一开始还担心这种贪心策略会出问题,然后来细思发现必定没什么问题,第一个一定为最长值,再考虑一下边界,于是顺利ac
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
string s,ns,temp;
int main()
{
//freopen("in.txt","r",stdin);
cin >> s;
int n = s.size();
int re = n;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
int num = 0;
int len = j-i+1;
ns = s.substr(i,len);
for(int pos=0;pos+len<=n;pos++)
{
temp = s.substr(pos,len);
if(temp == ns)
{
num++;
pos+= len - 1;
}
}
int tempre = n - num * (len - 1) + len;
if(tempre < re)
{
re = tempre;
//cout << ns << endl;
}
}
}
cout << re << endl;
return 0;
}
B 杨老师的游戏
思路:这才是本次比赛真正意义上的签到题,就是强行暴力枚举,首先生成9位数,共有9!种,再分别插入乘号和加号,计算,复杂度为O(9!*^3)=O(2.65*10^8)感觉海星,直接上代码,成功签到
这里,普及一个生成子串的好方法
do
{
……
}while(next_permutation(a,a+9));
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 1e5+10;
int a[9] = {1,2,3,4,5,6,7,8,9};
int main()
{
int n;
scanf("%d",&n);
int num = 0;
do
{
/*for(int i=0;i<5;i++)
{
cout << a[i];
}
cout << endl;*/
for(int mu=1;mu<9;mu++)
{
/*for(int de = 1;de<mu;de++)
{
int sum = 0;
int din = 0;
int din2 = 0;
for(int pos=0;pos<9;pos++)
{
if(pos < de)
{
sum = sum * 10 + a[pos];
}
else if(pos >= de && pos < mu)
{
din = din * 10 + a[pos];
}
else
{
din2 = din2 * 10 + a[pos];
}
}
sum -= din * din2;
if(sum == n)
{
num++;
for(int i=0;i<9;i++)
{
if(i == de)
{
cout << "-";
}
if(i == mu)
{
cout << "*";
}
cout << a[i];
}
cout << endl;
}
}*/
for(int de = mu+1;de<9;de++)
{
int sum = 0;
int din = 0;
int din2 = 0;
for(int pos=0;pos<9;pos++)
{
if(pos < mu)
{
din = din * 10 + a[pos];
}
else if(pos >= mu && pos < de)
{
din2 = din2 * 10 + a[pos];
}
else
{
sum = sum * 10 + a[pos];
}
}
sum = din * din2 - sum;
if(sum == n)
{
/*for(int i=0;i<9;i++)
{
if(i == de)
{
cout << "-";
}
if(i == mu)
{
cout << "*";
}
cout << a[i];
}
cout << endl;*/
num++;
}
}
}
}while(next_permutation(a,a+9));
printf("%d\n",num);
return 0;
}
C 勤奋的杨老师
思路:其实这题也挺好写的,典型题目,不过一开始看题出了点问题,将最多知识点看成了最多难度,导致怎么思索都无功而返,做完后面的难题折回来重读题才恍然大悟,这下的话就是个典型的lis问题了,前后两端lis取个和就ok
最后注意一下上升用lower_bound(),非降用upper_bound(),这也是lis里的一个小技巧
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 5e5+10;
int an[maxn];
int a[maxn];
int p1[maxn],p2[maxn];
//int pm1[maxn],pm2[maxn];
int main()
{
int num = 0,n;
cin >> n;
for(int i=0;i<n;i++)
{
cin >> an[i];
int pos = upper_bound(a,a+num,an[i]) - a;
if(pos == num)
{
a[num++] = an[i];
//pm1[i] = a[i];
}
else
{
a[pos] = an[i];
//pm1[i] = pm1[i-1];
}
p1[i] = num;
}
num = 0;
for(int i=n-1;i>=0;i--)
{
//cin >> an[i];
int pos = upper_bound(a,a+num,an[i]) - a;
if(pos == num)
{
a[num++] = an[i];
//pm2[i] = a[i];
}
else
{
a[pos] = an[i];
// pm2[i] = pm2[i-1];
}
p2[i] = num;
}
int re = max(p1[n-1],p2[0]);
for(int i=0;i<n-1;i++)
{
int temp = p1[i] + p2[i+1];
/*if(pm1[i] == pm2[i])
{
temp--;
}*/
if(temp> re)
{
re = temp;
//cout <<i<<"*" <<p1[i] << "*" << p2[i] << endl;;
}
}
cout << re << endl;
return 0;
}
F 猴子排序的期望
思路:由于最近这段时间做概率题做的比较多,刚看到这题的时候瞬间就很有兴趣,仔细研究发现其实是个大数题,估计最近要补一波java大数了,但在此之前本次还是老老实实写一份大数乘吧
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 5e5+10;
int an[maxn];
int a[maxn];
int p1[maxn],p2[maxn];
//int pm1[maxn],pm2[maxn];
int main()
{
int num = 0,n;
cin >> n;
for(int i=0;i<n;i++)
{
cin >> an[i];
int pos = upper_bound(a,a+num,an[i]) - a;
if(pos == num)
{
a[num++] = an[i];
//pm1[i] = a[i];
}
else
{
a[pos] = an[i];
//pm1[i] = pm1[i-1];
}
p1[i] = num;
}
num = 0;
for(int i=n-1;i>=0;i--)
{
//cin >> an[i];
int pos = upper_bound(a,a+num,an[i]) - a;
if(pos == num)
{
a[num++] = an[i];
//pm2[i] = a[i];
}
else
{
a[pos] = an[i];
// pm2[i] = pm2[i-1];
}
p2[i] = num;
}
int re = max(p1[n-1],p2[0]);
for(int i=0;i<n-1;i++)
{
int temp = p1[i] + p2[i+1];
/*if(pm1[i] == pm2[i])
{
temp--;
}*/
if(temp> re)
{
re = temp;
//cout <<i<<"*" <<p1[i] << "*" << p2[i] << endl;;
}
}
cout << re << endl;
return 0;
}
G chess
思路:这题是个老题了,看似博弈论敌对搜索什么的,其实就是个打表找规律,经典规律就是差值和小的数成黄金分割比的时候获胜,不多说,做过原题就毫无压力
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cmath>
using namespace std;
const double beauty = (1.0 + sqrt(5.0)) / 2.0;
int main()
{
int a,b;
while(scanf("%d%d",&a,&b)!=EOF)
{
if(a>b)
{
int temp = a;
a = b;
b = temp;
}
int di = b - a;
//cout << di << " " << (int)(double(di)*(beauty)) << endl;
if(a==(int)(double(di)*(beauty)))
{
printf("Lao Wang\n");
}
else
{
printf("Xiao Ren\n");
}
}
return 0;
}
H XOR
思路:在做a题迟迟无果的情况下,果断放弃,转投入h的怀抱
这题其实就是个变向Kruskal题,预处理一下异或和,然而对于复杂度是接受不了的,于是强行打表找规律,发现了分奇偶的规律
b[2*i] = 2*b[i] + i;
b[2*i-1] = 2*b[i] + i - 1;
然后一切就变得简单了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;
const int maxn = 2e4+10;
int b[maxn];
/*
typedef struct RODE
{
int x;
int y;
int pri;
}Road;
Road r[maxn];
bool cmp(const Road a,const Road b)
{
return a.pri < b.pri;
}
int pre[maxn];
int finds(int x)
{
int t = x;
while(t != pre[t])
{
t = pre[t];
}
int i = x;
while(pre[i] != t)
{
int temp =pre[i];
pre[i] = t;
i = temp;
}
return t;
}
void join(int x,int y)
{
x = finds(x);
y = finds(y);
if(x!=y)
{
if(x>y)
{
int temp = x;
x = y;
y = temp;
}
pre[y] = x;
}
return ;
}
void Kruskal(int n,int m)
{
for(int i=1;i<=n;i++)
{
pre[i] = i;
}
sort(r,r+m,cmp);
//for(int i=0;i<m;i++)
//{
// cout << r[i].pri << "#"<<endl;
//}
int lef = n;
int sum = 0;
for(int i=0;i<m;i++)
{
if(finds(r[i].x) != finds(r[i].y))
{
join(r[i].x, r[i].y);
sum += r[i].pri;
//cout << r[i].pri << endl;
//cout << r[i].x << "*" <<r[i].y << "*" << r[i].pri << endl;;
lef--;
if(lef == 1)
{
printf("%d\n",sum);
}
}
}
}
*/
int main()
{
int n;
b[2] = 1;
b[3] = 3;
b[4] = 4;
b[5] = 8;
b[6] = 9;
b[7] = 11;
for(int i=4;i<=10000;i++)
{
b[2*i] = 2*b[i] + i;
b[2*i-1] = 2*b[i] + i - 1;
}
while(scanf("%d",&n)!=EOF)
{
printf("%d\n",b[n]);
}
//cout << (int)(1^2) << endl;
//cout << (int)(0^1) << "*" << (int)(0^2) << "*" << (int)(0^3) << endl << (int)(1^2) << "*" << (int)(1^3) << endl << (int)(2^3) << endl;
//while(scanf("%d",&n)!=EOF)
/*for(int n=2;n<100;n++)
{
int m = 0;
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
r[m].x = i;
r[m].y = j;
r[m].pri = i^j;
m++;
//cout << i << "*" << j << "*" << m << endl;
}
}
//cout << m << endl;
Kruskal(n,m);
}*/
return 0;
}
/*b[2n] = 2b[n]+n;
b[2n+1] = 2b[n]+n+1;*/