소 여객 연습 경기

8496 단어
A  QAQ:
dp[i][0]는 앞의 i자 구성이 가능한'Q', dp[i][1]은 앞의 i자 구성이 가능한'QA', dp[i][2]는 앞의 i자 구성이 가능한'QAQ'를 의미한다.한 번 쓸면 된다.
#include
using namespace std;
#define ll long long
const int maxn=1e5+10;
char t[5005];
ll dp[maxn][3];
int main()
{
    scanf("%s",t+1);
    int len=strlen(t+1);
    for(int i=1;i<=len;i++)
    {
        if(t[i]=='Q')
        {
            dp[i][0]=dp[i-1][0]+1;
            dp[i][1]=dp[i-1][1];
            if(i>1)
                dp[i][2]=dp[i-2][1]+dp[i-1][2];
            else
                dp[i][2]=dp[i-1][2];
        }
        else if(t[i]=='A')
        {
            dp[i][0]=dp[i-1][0];
            if(i>1)
                dp[i][1]=dp[i-2][0]+dp[i-1][1];
            else
                dp[i][1]=dp[i-1][1];
            dp[i][2]=dp[i-1][2];
        }
        else
        {
            dp[i][0]=dp[i-1][0];
            dp[i][1]=dp[i-1][1];
            dp[i][2]=dp[i-1][2];
        }
    }
    printf("%lld
",dp[len][2]); return 0; }

B  Tic-Tac-Toe:
폭력 매거
#include
using namespace std;
char t[5][5],txt[5][5];
bool ok()
{
    for(int i=1;i<=3;i++)
    {
        bool flag=1;
        for(int j=1;j<=3;j++)
            if(txt[i][j]!='W')
                flag=0;
        if(flag)
            return 1;
        flag=1;
        for(int j=1;j<=3;j++)
            if(txt[j][i]!='W')
                flag=0;
        if(flag)
            return 1;
    }
    if(txt[1][1]=='W'&&txt[2][2]=='W'&&txt[3][3]=='W')
        return 1;
    if(txt[1][3]=='W'&&txt[2][2]=='W'&&txt[3][1]=='W')
        return 1;
    return 0;
}
bool cal()
{
    for(int i=1;i<=3;i++)
    {
        for(int j=1;j<=3;j++)
        {
            if(txt[i][j]=='#')
            {
                txt[i][j]='W';
                if(ok())
                    return 1;
                txt[i][j]='#';
            }
        }
    }
    return 0;
}
bool check2()
{
    for(int i=1;i<=3;i++)
    {
        for(int j=1;j<=3;j++)
        {
            if(t[i][j]=='W')
            {
                for(int i1=1;i1<=3;i1++)
                {
                    for(int j1=1;j1<=3;j1++)
                        txt[i1][j1]=t[i1][j1];
                }
                txt[i][j]='#';
                if(!cal())
                    return 1;
            }
        }
    }
    return 0;
}
bool check1()
{
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            txt[i][j]=t[i][j];
    if(cal())
        return 0;
    else
        return 1;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        for(int i=1;i<=3;i++)
            scanf("%s",t[i]+1);
        if(check1())
            printf("Bob
"); else if(check2()) printf("Emmm
"); else printf("Alice
"); } return 0; }

C  Buy Fruits:
n이 짝수인 경우, 예를 들어 n=10의 경우 다음과 같은 구조를 발견하면 된다.
9,7,5,3,1,0,8,6,4,2
홀수의 경우 n=1을 특판하고 기타 상황은 모두 불가능하다
#include
using namespace std;
int a[100005];
int main()
{
    int n;scanf("%d",&n);
    if(n==1)
        printf("0
"); else if(n%2) printf("-1
"); else { int x=n-1; for(int i=0;i

D  Data Structure
먼저 물어보지 않고 어떻게 최대치를 구할 수 있는지 생각해 보자.높은 자리에서 낮은 자리까지 고려하여 이 분이 취할 수 있다면 취하시오.취할 수 있는지 없는지는 욕심의 판단만 하면 된다. 첫 번째 수부터 스캔할 수 있다. 현재 수를 스캔할 때 그것들의 위치나 이전에 열거한 모든 취할 수 있는 위치를 포함하면 여기서 끊을 수 있다. 만약에 마지막에 k단보다 큰 단위로 나누면 된다.현재 수정 조작을 고려하고 있는데 1조작에 대해 x가 대응하는 2진법이 0이면 영향을 주지 않는다. 그렇지 않으면 모두 1이 되고 2조작에 대해 x가 대응하는 2진법이 1이면 영향을 주지 않는다. 그렇지 않으면 모두 0이 된다. 그래서 어느 한 사람이 영향을 미치면 그 다음에 이 사람은 반드시 0이 되거나 모두 1이 된다. 따라서 영향을 미치면 이 분을 단독으로 판단하면 된다.
#include
using namespace std;
const int maxn=2e5+10;
int a[maxn],n,k,Q;
int vis[33];
bool check(int x,int p)
{
    int X=x|(1<

=0;i--) { if(vis[i]==1&&(X>>i&1)) X^=(1<>i&1)) return 0; } int cnt=0,ans=0; for(int i=1;i<=n;i++) { cnt|=a[i]; if((cnt&X)==X) { cnt=0; ans++; } } return ans>=k; } int ask() { int ans=0; for(int i=30;i>=0;i--) if(check(ans,i)) ans^=(1<=0;i--) { if(x>>i&1) { if(vis[i]==0) { vis[i]=1; for(int j=1;j<=n;j++) a[j]|=(1<=0;i--) { if(!(x>>i&1)) { if(vis[i]==0) { vis[i]=2; for(int j=1;j<=n;j++) if(a[j]>>i&1) a[j]^=(1<>i&1) ans^=(1<


E   Pyramid
문제 풀이 여기.
F Magic Slab
대권 폐합자도.c[i][j]점을 선택했다면 a[i]와 b[j]는 반드시 선택해야 한다.관련 항목을 고려하면 각 관련 항목에 대해 다른 노드를 개척할 수 있다. 두 개의 관련 노드에 대해 각각 k를 가하고 새로 개척된 노드에 대해 k를 빼면 두 개의 관련 노드가 하나만 가면 1 더하기 1 빼기는 딱 상쇄한다. 만약에 두 개를 모두 취하면 두 번에 한 번 더하기 1은 빼면 k를 가하는 것과 같다. 만약에 두 점을 모두 취하지 않으면 영향이 없다.
#include
using namespace std;
const int maxn=20005;
const int inf=1e9;
struct node
{
    int to,cap,rev;
    node(int _to=0,int _cap=0,int _rev=0)
    {
        to=_to;
        cap=_cap;
        rev=_rev;
    }
};
vectorG[maxn];
int level[maxn],iter[maxn];
void add_edge(int from,int to,int cap)
{
    node e=node(to,cap,G[to].size());
    G[from].push_back(e);
    e=node(from,0,G[from].size()-1);
    G[to].push_back(e);
}

void bfs(int s)
{
    memset(level,-1,sizeof(level));
    queueque;
    level[s]=0;
    que.push(s);
    while(!que.empty())
    {
        int v=que.front();que.pop();
        for(int i=0;i0&&level[e.to]<0)
            {
                level[e.to]=level[v]+1;
                que.push(e.to);
            }
        }
    }
}

int dfs(int v,int t,int f)
{
    if(v==t)
        return f;
    for(int &i=iter[v];i0&&level[v]0)
            {
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(int s,int t)
{
    int flow=0;
    while(1)
    {
        bfs(s);
        if(level[t]<0)
            return flow;
        memset(iter,0,sizeof(iter));
        int f;
        while((f=dfs(s,t,inf))>0)
            flow+=f;
    }
    return flow;
}

int a[44],b[44],c[44][44],mp[20002];
int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&c[i][j]);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            sum+=c[i][j];
            int s=(i-1)*n+j;
            int t=n*n+i;
            mp[s]=c[i][j];
            add_edge(s,t,inf);
            t=n*n+n+j;
            add_edge(s,t,inf);
        }
        mp[n*n+i]=-a[i];
        mp[n*n+n+i]=-b[i];
    }
    for(int i=1;i<=m;i++)
    {
        int x1,y1,x2,y2,k;
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);
        add_edge((x1-1)*n+y1,n*n+2*n+i,inf);
        add_edge((x2-1)*n+y2,n*n+2*n+i,inf);
        mp[(x1-1)*n+y1]+=k;
        mp[(x2-1)*n+y2]+=k;
        mp[n*n+2*n+i]-=k;
        sum+=2*k;
    }
    int S=0,T=n*n+2*n+m+1;
    for(int i=1;i0)
            add_edge(S,i,mp[i]);
        else
            add_edge(i,T,-mp[i]);
    }
    printf("%d
",sum-max_flow(S,T)); return 0; }

좋은 웹페이지 즐겨찾기