ICPC Japan IISF 2018 solve(5/8)

A題:給你n個數,問你有多少數<=n個數和/n.

方法:求個和,跑一邊判斷每個數*n是不是小於等於和。

B題:給你n*m的一個紙,然後模擬2種操作,一種是從左往右摺疊,一種是從下往上摺疊,然後p次詢問,在某點打孔能打透多少紙,直接模擬下過程即可。

int geta(int i,int j)
{
    if(i<0||i>=n||j<0||j>=m)return 0;
    return a[i][j];
}
int main()
{
    while(scanf("%d%d%d%d",&n,&m,&t,&p),n)
    {
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                a[i][j]=1;
        while(t--)
        {
            scanf("%d%d",&x,&y); //1 lr  2du
            if(x==1)
            {
                for(int i=0;i<n;i++)
                {
                    for(int j=0;j<m;j++)
                    {
                        b[i][j]=geta(y+i,j)+geta(y-1-i,j);
                    }
                }
                for(int i=0;i<n;i++)
                    for(int j=0;j<m;j++)
                        a[i][j]=b[i][j];
            }
            else
            {
                for(int i=0;i<n;i++)
                {
                    for(int j=0;j<m;j++)
                    {
                        b[i][j]=geta(i,y+j)+geta(i,y-1-j);
                    }
                }
                for(int i=0;i<n;i++)
                    for(int j=0;j<m;j++)
                        a[i][j]=b[i][j];
            }
        }
        while(p--)
        {
            scanf("%d%d",&x,&y);
            printf("%d\n",a[x][y]);
        }
    }
    return 0;
}

C題

題意:給你一個數,問你讓最多的連續的數的和等於它,然後問你起始點在哪裏,長度是多少。

思想:直接枚舉肯定GG,化簡等差數列求和公式即可,然後考慮枚舉的最多不會超過sqrt(2*n),暴力枚舉長度,公式計算起始點,最大的那個直接輸出。

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
int main()
{
    ll n;
    while(scanf("%lld",&n)!=EOF)
    {
        if(n==0)
            break;
        ll len=(sqrt(2*n));
        ll ans;
        for(;len>=1;len--)
        {
            ll x=(2*n-len*len+len)/2/len;
            if(len*(x+x+len-1)/2==n)
            {
                ans=x;
                break;
            }
        }
        printf("%lld %lld\n",ans,len);
    }
    return 0;
}

D題:

給你奇數個球隊,想要形成一種局面,就是每個球隊勝利和失敗的次數一樣多,問你有多少種不同的結果。

看到n不大直接想到dfs,每個隊伍的贏不會超過(n-1)/2,這樣來判斷T到懷疑人生,然後看了看別人的,發現自己傻了,直接搜索的時候一個三角形即可,然後在用兩個隊伍的lose次數和win次數來限制,這樣搜索的更少了。

從(1,2)或者(n,1)搜都比較好寫判斷,下面給(1,2) (n,1)自己寫下。

#include<bits/stdc++.h>
using namespace std;
int win[10];//標記勝利的次數
int los[10];
int vis[10][10];//標記勝利 
long long ans;
int n,m,temp;
void dfs(int x,int y)
{
    if(y==n+1)//換行 
    {
        x++;
        y=x+1;  
    } 
    if(x==n)//到達終點 
    {
        ans++;
        return ;
    }
    if(vis[x][y]==1)
        dfs(x,y+1);
    else//是一個不確定的點 
    {
        //printf("%d %d %d %d  %d\n",x,win[x],y,los[y],temp);
        if(win[x]<temp && los[y]<temp)
        {
            win[x]++;
            los[y]++;
            dfs(x,y+1);
            win[x]--;
            los[y]--; 
        } 
        if(win[y]<temp && los[x]<temp)
        {
            win[y]++;
            los[x]++;
            dfs(x,y+1);
            win[y]--;
            los[x]--;
        }
    } 
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
            break;
        memset(vis,0,sizeof(vis));
        memset(win,0,sizeof(win));
        memset(los,0,sizeof(los)); 
        scanf("%d",&m);
        int flag=1; 
        temp=(n-1)/2;
        for(int i=0;i<m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            win[a]++;
            los[b]++;
            vis[a][b]=1;//標記打過了 
            vis[b][a]=1;
            if(win[a]>(n-1)/2 || los[b]>(n-1)/2)
                flag=0; 
        } 
        if(flag==0)
        {
            printf("0\n");
            continue;
        }
        ans=0; 
        dfs(1,2);
        printf("%lld\n",ans);
    }
    return 0;
}

E題:

 E題不多解釋了,隊友賽後搞掉的,問了隊友,然後沉思很久,然後噼裏啪啦,然後過了示例,然後WA,然後看了看代碼,嗯,寫錯了,一頓噼裏啪啦,過了。

貼下隊友博客:https://blog.csdn.net/winter2121/article/details/81986176

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章