zoukankan      html  css  js  c++  java
  • Codeforces Round #686 (Div. 3)(A->D)(模拟,vector,数学)

    A:https://codeforces.com/contest/1454/problem/A

    题意:

    输出1~n的一个排列,满足每个i!=pi

    解析:

    偶数直接倒叙

    奇数不能倒叙,因为中间点不符合。所以随便调下位置即可。比如先输出n,然后正序输出1~n-1

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<stack>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    int main()
    {    
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            if(n%2)
            {
                cout<<n<<" ";
                for(int i=1;i<=n-1;i++)
                    cout<<i<<" ";
            }
            else
            {
                for(int i=n;i>=1;i--)
                    cout<<i<<" ";
            }
            cout<<endl;
        }
    }

    B:https://codeforces.com/contest/1454/problem/B

    题意:

    给出n个数,是否某个数只出现了一次,而且在所有出现一次的数中最小。

    解析:

    俩memset hack掉了。

    其实计坐标的那个数组压根不需要重置。每次都被覆盖了。。。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int a[maxn];
    int v1[maxn],v2[maxn];
    int main()
    {    
        int t;
        cin>>t;
        while(t--)
        {
            memset(v1,0,sizeof(v1));
            int n;
            cin>>n;
            for(int i=1;i<=n;i++)
            {
                int x;
                cin>>x;
                v1[x]++;
                v2[x]=i;
            }
            int ok=0,idx;
            for(int i=1;i<=n;i++)
            {
                if(v1[i]==1)
                {
                    ok=1;
                    idx=v2[i];
                    break;
                }
            }
            if(ok)
                cout<<idx<<endl;
            else
                cout<<"-1"<<endl;
        }
    }

    C:https://codeforces.com/contest/1454/problem/C

    题意:

    给出n个数

    只能选择一个数字x,然后每次都要消一个[L,R],[L,R]中不能包含x

    使得数列全相等的最少操作数

    解析:

    开始以为是贪心,但是光看样例就给否定了。原来是个模拟。

    那么就考虑,对每个数字的出现位置进行记录,每次算一下如果选它需要的操作数,取个最小值就行了。

    但是细节是颇多的。其实对比别人的话,我是写的有点太丑了。。。。。vector写的比较简单,看来还是太菜了。。。

    具体注释看代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    const int inf=99999999;
    int a[maxn];
    int v1[maxn],v2[maxn];
    int main()
    {    
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            for(int i=1;i<=n;i++)
                v1[i]=0;
            memset(v2,0,sizeof(v2));//记录每个数的操作数
            map<int,int>mp;//记录出现次数
            int minn=inf;int maxx=0;
            int sum=0;
            for(int i=1;i<=n;i++)
            {
                cin>>a[i];
                int cnt=0;
                mp[a[i]]++;
                if(v1[a[i]]==0)//之前没出现过
                {
                    if(i==1)//目前处于开头,那么不需要操作
                        cnt=0;
                    else
                        cnt=1;
                }
                else
                {
                    if(v1[a[i]]+1==i)//如果出现过,而且和上次出现位置相邻,不需操作
                        cnt=0;
                    else
                        cnt=1;
                }
                v1[a[i]]=i;
                v2[a[i]]+=cnt;            
            }
            for(int i=1;i<=n;i++)//对最后出现不在末尾的,操作+1
            {
                if(v1[i]<n&&mp[i]>0)
                {
                    
                    v2[i]++;
                }
            }
    //        for(int i=1;i<=n;i++)
    //            cout<<v2[i]<<" ";
    //            cout<<"--"<<endl;
            int ok=0;
            for(int i=1;i<n;i++)
            {
                if(a[i]!=a[i+1])
                {
                    ok=1;
                    break;
                }
            }
            if(ok==0)  //全相等
                cout<<"0"<<endl;
            else
            {for(int i=1;i<=n;i++)
                {
                    if(v2[i]!=0)
                    minn=min(minn,v2[i]);
                }
                cout<<minn<<endl;
            }
        }
    }

    来个vector版的吧,vector<vector<int>>v(n+10);

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<stack>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    const int inf=99999999;
    int a[maxn];
    int v1[maxn],v2[maxn];
    int main()
    {    
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            int x;
            vector<vector<int>>v(n+10);
            for(int i=1;i<=n;i++)
            {
                cin>>x;
                v[x].push_back(i);
            }
            int minn=inf;
            for(int i=1;i<=n;i++)
            {
                if(v[i].empty())
                    continue;
                int md=2;//默认i的个出现位置,都处于2~n-1之间,所以默认操作2次
                for(int j = 1 ; j < v[i].size();j++)//算的是所有数之间,不包括两边
                {
                    if(v[i][j]>v[i][j-1]+1)//不相邻
                        md++;
                }
                if(v[i][0]==1)//初始处于第一个位置,md--
                    md--;
                if(v[i][v[i].size()-1]==n)//同理
                    md--;
                minn=min(minn,md);
            }
            cout<<minn<<endl;
        }
        return 0;
    }

    D:https://codeforces.com/contest/1454/problem/D

    题意:

    给出n

    输出最长的一组数,它们的乘积能被n整除。而且ai能够整除ai-1

    解析:

    根据唯一分解定理:

    找出出现次数最多的质因子,设出现次数x

    那么先输出前x-1个,然后剩下那个乘到其他因数上变成一体就好了。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int a[maxn];
    int v1[maxn],v2[maxn];
    int main()
    {    
        int t;
        cin>>t;
        while(t--)
        {
            ll n,nn;
            cin>>n;
            nn=n;
            int sum=0;
            map<ll,int>m;
            for(int i=2;i<=n/i;i++)
            {
                while(n%i==0)
                {
                    n=n/i;
                    m[i]++;
                    sum++;
                }
            }
            if(n>1)
            {
                m[n]++;
                sum++;
            }
            ll maxx=0;
            ll md;
            for(int i=2;i<=nn/i;i++)
            {
                if(nn%i==0)
                {
                    if(maxx<m[i])
                    {
                        maxx=m[i];
                        md=i;
                    }
                }
            }
            if(maxx==0)
                maxx=1;
            cout<<maxx<<endl;
            ll all=1;
            for(int i=1;i<=maxx-1;i++)
            {
                cout<<md<<" ";
                all*=md;
                m[md]--;
            }
            cout<<nn/all<<endl;    
        }
        return 0;
    }
  • 相关阅读:
    parent和top
    history
    [矩阵快速幂]T-shirt(2018江苏邀请赛I题)
    [学习]Java学习
    [数论]Factors of Factorial
    [RMQ][ST算法]Frequent values
    [二维树状数组]计数问题
    [树状数组]Mishka and Interesting sum(codeforces703D)
    [简单思维题]Snuke's Coloring 2-1
    [树状数组][逆序数]Ultra-QuickSort
  • 原文地址:https://www.cnblogs.com/liyexin/p/14038484.html
Copyright © 2011-2022 走看看