Codeforces Round #632 (Div. 2)A-D、F

https://codeforces.com/contest/1333

A. Little Artem

  • 題目大意:構造一個n×mn×m的矩陣:1、只有黑白兩種顏色;2、要滿足B=W+1B=W+1(B表示黑色單元格的個數,並且這些單元格周圍至少有一個白色單元格,W類似)
  • 思路:在左上角的一個單元格塗上白色(與它相鄰的單元格剛好只有兩個),其他全塗黑色
#include <iostream>
#include <stdio.h>
#include <algorithm>
//#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=1e5+10;
void black(int n)
{
    for(int i=0;i<n;i++)
        printf("B");
    printf("\n");
}
void white(int n)
{
    for(int i=0;i<n;i++)
        printf("W");
}
int main()
{
    int t,n,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        white(1);
        black(m-1);
        for(int i=1;i<n;i++)
            black(m);
    }
    return 0;
}

B. Kind Anton

  • 題目大意:給定長度均爲n的兩個數列aba、ba[i]a[i]只能是1,0,11,0,-1中的一個數,問是否能執行若干次操作a[j]+=a[i]1i<jn:a[j]+=a[i](1≤i<j≤n)使數列aa與數列bb相等
  • 因爲只能將前面的數累加到後面,所以當a[i]<b[i]a[i]<b[i]時,只用看a[1]a[1]a[i1]a[i-1]中有沒有1;a[i]>b[i]a[i]>b[i]時,就看前面有沒有-1(有的人想着想着就忘了i<j :)……
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=1e5+10;
int main()
{
    int t,n,a[manx],b;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int f_1=0,f1=0,ans=1;
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&b);
            if(ans&&a[i]>b&&f_1==0)
                ans=0;
            if(ans&&a[i]<b&&f1==0)
                ans=0;
            if(a[i]==-1)
                f_1=1;
            else if(a[i]==1)
                f1=1;
        }
        if(ans)
            printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

C. Eugene and an array

  • 題目大意:給定一個長度爲n的序列(1n2e5)(1≤n≤2e5 ),定義good array 爲不含有和爲0的連續子序列,問這個序列中有多少個good array
  • 思路:我們可以求一次前綴和,如果某兩個前綴和相等sum[i]==sum[j]sum[i]==sum[j],就說明[i+1,j][i+1,j]這段子序列和爲0。因爲我們找的這些子序列中不能含有某段和爲0的連續子序列,所以,我們可以記錄這些序列的左端點的最大值爲p,處理到第i位時,以i結尾的good array 個數就等於i(p+1)i-(p+1)
//爲了避免討論不存在相等前綴和和其他特殊情況情況,所以在序列前面加了一個0
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <map>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=2e5+10;
map<int,int>mp;
signed main()
{
    int n,a,ans=0,psum=0,p=0;
    scanf("%lld",&n);
    mp[0]=1;
    for(int i=2;i<=n+1;i++)
    {
        scanf("%lld",&a);
        psum+=a;
        p=max(p,mp[psum]);
        ans+=i-p-1;
        mp[psum]=i;
    }
    printf("%lld",ans);
    return 0;
}

D. Challenges in school №41

  • 題目大意:n個人站成一排,要麼朝向左邊,要麼朝向右邊。如果兩個人相鄰且 looking at each other ,那麼他們兩個人可以在1s以內轉向和原來相反的方向。問:是否存在一種步驟,使他們在k秒後不存在相鄰且對視的情況。(多解)
  • 思路:在1s內,可能不止一對人滿足可以同時轉向另一面的條件,但是他們之間是互不影響的,比如“RLRL”中第三個人肯定是和第四個人同時轉向,而不會是1、2兩個人轉向後,2、3兩個人也能滿足同時轉向的條件(感覺說不太清楚地樣子)。所以我們可以先處理出最短的時間,即在每1s內能夠轉向的都轉向,一直重複這個步驟,直到不存在相鄰且對視的情況(ps:題目有保證說轉向次數不會超過n2次,且n<3e3)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <vector>
//#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=3e3+10;
char str[manx];
int a[manx][manx],n,k,cou=0,sum=0;
int main()
{
    scanf("%d%d",&n,&k);
    scanf("%s",str+1);
    for(int i=0;i<=n;i++)
        a[i][0]=0;
    while(1)
    {
        for(int i=1;i<n;i++)
        {
            if(str[i]=='R'&&str[i+1]=='L')
            {
                a[cou][0]++;
                a[cou][a[cou][0]]=i;
                str[i]='L';
                str[i+1]='R';
                i++;
            }
        }
        if(!a[cou][0])break;
        sum+=a[cou][0];
        cou++;
    }
    if(sum<k||cou>k)
    {
        printf("-1\n");
        return 0;
    }
    for(int i=0;i<cou;)
    {
        if(cou-i==k)
        {
            printf("%d",a[i][0]);
            for(int j=1;j<=a[i][0];j++)
                printf(" %d",a[i][j]);
            printf("\n");
            i++;
            k--;
        }
        else
        {
            printf("1 %d\n",a[i][a[i][0]]);
            a[i][0]--;
            if(!a[i][0])
                i++;
            k--;
        }
    }
    return 0;
}

F. Kate and imperfection

  • 題目大意:一個包含n個數:1、2、3……n的集合S,(一個集合中存在最大的__gcd()\_\_gcd()值)求S的k個元素的子集中,最小的__gcd()“最大\_\_gcd()”,k=2、3、4……n.
  • 思路:首先k=n時,最小的__gcd()“最大\_\_gcd()”很容易求出(因爲n個元素的子集只有一個);要使k=n-1時,__gcd()“最大\_\_gcd()”最小,就應該刪去n個元素中產生__gcd()“最大\_\_gcd()”的數。因爲是連續的n個數,所以每個數能產生的最大__gcd()值就是它的最大因子(不含本身),將這些最大因子排序,逐個輸出就可以了
  • O(nlogn):也可以用素數打表裏面的線性篩,因爲線性篩裏面每個數只被它的最小因子篩選一次,所以就能夠很容易得到它的最大因子
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
//#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=5e5+10;
int a[manx];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int flag=1;
        for(int j=2;j*j<=n;j++)
        {
            if(i%j==0)
            {
                flag=i/j;
                break;
            }
        }
        a[i]=flag;
    }
    sort(a+1,a+n+1);
    for(int i=2;i<=n;i++)
        printf("%d ",a[i]);
    printf("\n");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章