新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)

五一期间,怎么能闲着,好久都没打大型个人赛了,来一场找找感觉

总的难度感觉还可以,最终六题收场,海星

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;*/


发布了97 篇原创文章 · 获赞 89 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Owen_Q/article/details/80268003