ICPC Japan IISF 2018 solve(5/8)

7 篇文章 0 订阅

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值