xdoj freshmen onsite 2018

不知不觉到了第二届新生赛,此时的我已经是退休老油条了,看着xdu-icpc队伍逐渐壮大,甚是欣慰。预祝即将到来的第三届新生赛顺利。

Problem A Easy Problem 

思路:正奇数数列最大长度,打标找规律即可发现,答案即为输入的开方数

#include <bits/stdc++.h>
 
using namespace std;
 
const double eps = 1e-5;
 
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        printf("%d\n",(int)sqrt(double(n)+eps));
    }
    return 0;
}

Problem B 希希的多项式 

思路:多项式找规律

*   **  n0=1
1   00  n1=x
1   -1  n2=x^2-1
1   -3  n3=x^3-3x
1   -6  n4=x^4-6x^2+3
1   -10 n5=x^5-10x^3+15x
1   -15 n6=x^6-15x^4+45x^2-15

总结不难发现,第一项必为1,第二项为前n项和

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        long long re = (-1LL) * (long long)(n) * (long long)(n-1) / 2LL;
        printf("%d %lld\n",1,re);
    }
    return 0;
}

Problem C 编辑器的选择 

思路:16进制乘法,进制转换,说白了其实这题最大的难度在数据读入上,含空格的整行读取,当然是while(getline(cin,in))。最后注意一下string的初始化

#include <bits/stdc++.h>
 
using namespace std;
 
map<string,int> dic;
 
int main()
{
    dic["zero"]=0;
    dic["one"]=1;
    dic["two"]=2;
    dic["three"]=3;
    dic["four"]=4;
    dic["five"]=5;
    dic["six"]=6;
    dic["seven"]=7;
    dic["eight"]=8;
    dic["nine"]=9;
    dic["ten"]=10;
    dic["eleven"]=11;
    dic["twelve"]=12;
    dic["thirteen"]=13;
    dic["fourteen"]=14;
    dic["fifteen"]=15;
    string in;
    while(getline(cin,in))
    {
        int a=0,b=0;
        string temp = "";
        int len = in.size();
        for(int i=0;i<len;i++)
        {
            if(in[i]==' ')
            {
                //cout << temp << endl;
                a = a*16 + dic[temp];
                temp.clear();
                //cout << a << endl;
            }
            else
                temp += in[i];
        }
        a = a*16 + dic[temp];
        getline(cin,in);
        len = in.size();
        temp.clear();
        for(int i=0;i<len;i++)
        {
            if(in[i]==' ')
            {
                b = b*16 + dic[temp];
                temp.clear();
            }
            else
                temp += in[i];
        }
        b = b*16 + dic[temp];
        //cout << a << " " << b << endl;
        cout << a*b << "\n";
    }
    return 0;
}

Problem D Love Live! 南琴梨篇

思路:寻找树上两点的公共子序列(LCA)。看似是到很复杂的lca题,但由于树的特殊性,相同前缀的数必定在相同分叉上,于是这题就转换为了求两串的最长公共前缀

#include <bits/stdc++.h>
 
using namespace std;
 
const int maxn = 1e4+5;
 
char a[maxn],b[maxn],re[maxn];
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int k;
        scanf("%d%s%s",&k,a,b);
        int alen = strlen(a), blen = strlen(b);
        int pos = 0;
        while(pos<alen&&pos<blen&&a[pos]==b[pos])
        {
            re[pos]=a[pos];
            pos++;
        }
        if(pos==0)
            printf("I'm sorry, KOTORI!");
        else
            for(int i=0;i<pos;i++)
                printf("%c",re[i]);
        printf("\n");
    }
    return 0;
}

Problem E or2?Scum! 

思路:判断某个数是否为2,3,5,7的公约数,且为第几大公约数,貌似和素数很像,瞬间又成为一个十分困难的数学问题。实则不然,判断第几大公约数,即为求比该数小的公约数有多少个,那么完全可以分别求比该数小的2,3,5,7个字的约数,之后根据容斥定理即可得出

#include <bits/stdc++.h>
 
using namespace std;
 
const double eps = 1e-5;
 
int main()
{
    long long n;
    while(scanf("%lld",&n)!=EOF)
    {
        if(n%2==0||n%3==0||n%5==0||n%7==0)
        {
            /*long long sum = (long long)(((double)n-eps)/2.0) + (long long)(((double)n-eps)/3.0) + (long long)(((double)n-eps)/5.0) + (long long)(((double)n-eps)/7.0);
            sum = sum - (long long)(((double)n-eps)/6.0) - (long long)(((double)n-eps)/10.0) - (long long)(((double)n-eps)/14.0) - (long long)(((double)n-eps)/15.0) - (long long)(((double)n-eps)/21.0) - (long long)(((double)n-eps)/35.0);
            sum = sum + (long long)(((double)n-eps)/30.0) + (long long)(((double)n-eps)/42.0) + (long long)(((double)n-eps)/70.0) + (long long)(((double)n-eps)/105.0);
            sum -= (long long)(((double)n-eps)/210.0);*/
            long long sum = n/2LL +n/3LL + n/5LL + n/7LL;
            sum = sum - n/6LL - n/10LL - n/14LL - n/15LL - n/21LL - n/35LL;
            sum = sum + n/30LL + n/42LL + n/70LL + n/105LL;
            sum -= n/210LL;
            printf("or2 %lld\n",sum);
        }
        else
            printf("Scum\n");
    }
    return 0;
}

Problem F zxy的长跑

思路:寻找最小欧拉回路,看似简单的题意,实则坑点十足

首先,可能含有多重变,其次,可能含有孤立点,处理不好的话这两个坑点足以让人崩溃,最后dfs记得回溯即可

#include <bits/stdc++.h>
 
using namespace std;
 
const int maxn = 510;
 
int ma[maxn][maxn];
//vector<int> ne[maxn];
//bool point[maxn];
//vector<int> re;
int re[maxn];
int ne[maxn];
 
int dfs(int p,int m,int n,int repos)
{
    for(int i=1;i<=n;i++)
    {
        //if(st==i)
            //continue;
        if(repos<m&&ne[i]==1)
            continue;
        if(ma[p][i]>0)
        {
            ne[i]--;
            ne[p]--;
            ma[p][i]--;
            ma[i][p]--;
            //re.push_back(i);
            re[repos++] = i;
            //cout << i << "*" << repos << endl;
            repos = dfs(i,m,n,repos);
            if(repos<m+1)
            {
                ne[i]++;
                ne[p]++;
                ma[p][i]++;
                ma[i][p]++;
                repos--;
            }
            else
                break;
            //cout << pos << "*" << st << endl;
            //st = i;
            //break;
        }
    }
    return repos;
}
 
int main()
{
    memset(ma,0,sizeof ma);
    //memset(point,false,sizeof point);
    memset(ne,0,sizeof ne);
    //re.clear();
    int repos = 0;
    int n,m;
    scanf("%d%d",&n,&m);
    /*for(int i=1;i<=n;i++)
    {
        ne[i].clear();
        point[i].false;
    }*/
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        //ne[a].push_back(b);
        //ne[b].push_back(a);
        ma[a][b]++;
        ma[b][a]++;
        ne[a]++;
        ne[b]++;
    }
    int collect = 0;
    for(int i=1;i<=n;i++)
    {
        /*if(ne[i].size()%2==1)
        {
            point[i] = true;
            collect++;
        }*/
        if(ne[i]%2==1)
        {
            //point[i] = true;
            collect++;
        }
    }
    //cout << collect << endl;
    if(collect>2)
        printf("-1\n");
    else
    {
        int st = 1;
        while(ne[st]==0)
            st++;
        //cout << st << endl;
        if(collect==2)
        {
            for(int i=st;i<=n;i++)
            {
                if(ne[i]%2==1)
                {
                    st=i;
                    break;
                }
            }
        }
        //re.push_back(st);
        re[repos++] = st;
        repos = dfs(st,m,n,repos);
        /*int pos;
        for(pos=0;pos<m;pos++)
        {
            int i;
            for(i=1;i<=n;i++)
            {
                //if(st==i)
                    //continue;
                if(pos<(m-1)&&ne[i]==1)
                    continue;
                if(ma[st][i]>0)
                {
                    ne[i]--;
                    ne[st]--;
                    ma[st][i]--;
                    ma[i][st]--;
                    re.push_back(i);
                    //cout << pos << "*" << st << endl;
                    st = i;
                    break;
                }
            }
            if(i==n+1)
                break;
        }
        //cout << pos << endl;
        if(pos<m)*/
        if(repos<m+1)
            printf("-1\n");
        else
        {
            //cout << re.size() << "*" << re[0] << " " << re[1] << "*" << m << endl;
            for(int i=0;i<m;i++)
                printf("%d ",re[i]);
            printf("%d\n",re[m]);
        }
    }
    return 0;
}

Problem G Twilight7和偶像 

思路:和去年的那题类似,区间扫描点排序,不多说了

#include <bits/stdc++.h>
 
using namespace std;
 
const int maxn = 1e5+5;
 
/*typedef struct POINT
{
    int pos;
    int mak;
}Point;
 
bool cmp(Point a,Point b)
{
    if(a.mak>b.mak)
        return true;
    else if(a.mak==b.mak)
    {
        if(a.pos>b.pos)
            return true;
        else
            return false;
    }
    else
        return false;
}
 
Point num[maxn];*/
int tmp[maxn];
int num[maxn];
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(num,0,sizeof num);
        memset(tmp,0,sizeof tmp);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            int p,q;
            scanf("%d%d",&p,&q);
            tmp[p]++;
            tmp[q+1]--;
        }
        int now = 0;
        for(int i=1;i<=n;i++)
        {
            now += tmp[i];
            //num[i-1].pos = i;
            //num[i-1].mak = now;
            num[i-1]=now;
        }
        //sort(num,num+n,cmp);
        sort(num,num+n,greater<int>());
        long long re = 0LL;
        for(int i=0;i<n;i++)
            re += (long long)(i+1) * (long long)(num[i]);
        printf("%lld\n",re);
    }
    return 0;
}
发布了97 篇原创文章 · 获赞 89 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Owen_Q/article/details/100549133
今日推荐