The 2018 ACM-ICPC Asia Qingdao Regional Contest

施工中(8/13)

题目链接:https://vjudge.net/contest/269632#overview

 

C - Flippy Sequence 

 

队友写的,没看题

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
char a[N],b[N];
int c[N];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll n;
        scanf("%lld",&n);
        scanf("%s",a);
        scanf("%s",b);
        int num=0;
        for(int i=1;i<=n;i++)
        {
            if(a[i-1]==b[i-1])
                c[i]=0;
            else
            {
                c[i]=1;
                if(c[i-1]==0)
                    num++;
            }
        }
        if(num==0)
        {
            printf("%lld\n",n*(n+1)/2);
        }
        else if(num==1)
        {
            printf("%lld\n",2*(n-1));
        }
        else if(num==2)
        {
            printf("6\n");
        }
        else
        {
            printf("0\n");
        }
    }
    return 0;
}

D - Magic Multiplication 

 

如果能发现,枚举第一位后,后面的所有数都是固定的,就模拟了

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
int a[MAXN],b[MAXN];
char s[MAXN];
int n,m,len,tim;
bool getb()
{
    int tot=0;
    tim++;
    for(int &i=tim;i<=len&&tot<m;i++)
    {
        int now=s[i]-'0';
        if(now%a[1]==0)
        {
            b[++tot]=now/a[1];
        }
        else
        {
            if(i==len) return false;
            now=now*10+s[++i]-'0';
            if(now%a[1]==0&&now/a[1]<=9)
            {
                b[++tot]=now/a[1];
            }
            else
            {
                return false;
            }
        }
    }
    if(b[1]==0) return false;
    if(tot!=m) return false;
    return true;
}
bool geta()
{
    int tot=1;
    int nowb=1;
    for(int &i=tim;i<=len;i++,nowb++)
    {
        if(nowb>m) nowb-=m;
        int now=s[i]-'0';
        if(b[nowb]==0)
        {
        	if(now==0) 
			{
				if(nowb==1)
					a[++tot]=0;
				continue;
			}
        	else return false;
		}
        if(now%b[nowb]==0)
        {
            if(nowb==1)
                a[++tot]=now/b[nowb];
            else if(now/b[nowb]!=a[tot])
                return false;
        }
        else
        {
            if(i==len) return false;
            now=now*10+s[++i]-'0';
            if(now%b[nowb]==0&&now/b[nowb]<=9)
            {
                if(nowb==1)
                    a[++tot]=now/b[nowb];
                else if(now/b[nowb]!=a[tot])
                    return false;
            }
            else
            {
                return false;
            }
        }
    }
    if(tim!=len+1) return false;
    if(tot!=n) return false;
    return true;
}
void print()
{
    for(int i=1;i<=n;i++)
        printf("%d",a[i]);
    printf(" ");
    for(int i=1;i<=m;i++)
        printf("%d",b[i]);
    puts("");
}
void solve()
{
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    len=strlen(s+1);
    for(int i=1;i<=9;i++)
    {
        a[1]=i;
        tim=0;
        if(!getb())
        {
            continue;
        }
        if(!geta())
        {
            continue;
        }
        print();
        return ;
    }
    puts("Impossible");
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}

E - Plants vs. Zombies

 

二分一个答案,然后从左到右贪心去做即可

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
ll a[N],b[N];
ll n,m;
ll judge(ll val)
{
    ll all = 0;
    ll ans = 0;
    for(int i=1;i<=n;i++)
    {
        b[i] = val / a[i] + (val % a[i]>0?1:0);
        all += b[i];
        if(all > m)
            return 0;
    }
    b[0]=0;b[n+1]=0;
    for(int i=1;i<=n;i++)
    {
        ans += b[i-1]*2+1;
        b[i]-=b[i-1]+1;
        if(b[i] < 0 && i==n)
        {
            ans --;
        }
        b[i]=max(b[i],0ll);
        b[i-1]=0;
        if(ans > m)
            return 0;
    }
    ans += b[n]*2;
    if(ans>m)
        return 0;
    return 1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        ll l=0,r=1e18,mid;
        ll ans=0;
        while(l<=r)
        {
            mid = (l+r)/2;
            if(judge(mid))
            {
                ans = mid;
                l=mid+1;
            }
            else
                r=mid-1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

F - Tournament

 

找规律即可

 

代码:

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int MAXN=1005;
int n,k;
int a[MAXN][MAXN];
void solve()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=k;i++)
    {
        for(int j=1;j<=n;j++)
        {
            a[i][j]=0;
        }
    }
    for(int i=1;i<=k;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(a[i][j]==0)
            {
                if(j+i>n)
                {
                    puts("Impossible");
                    return ;
                }
                a[i][j]=j+i;
                a[i][j+i]=j;
                for(int p=1;p<i;p++)
                {
                    a[i][a[p][j]]=a[p][i+j];
                    a[i][a[p][i+j]]=a[p][j];
                }
            }
        }
    }
    for(int i=1;i<=k;i++)
    {
        printf("%d",a[i][1]);
        for(int j=2;j<=n;j++)
        {
            printf(" %d",a[i][j]);
        }
        puts("");
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
}

G - Repair the Artwork

 

首先发现,最多只有n方中不同的方法,然后dp[i][j]表示到i这个点,放了j种不同的方法,有多少方案数,然后在每个非0的地方来转移,容斥掉那些不合法的方案,n的四次方即可

 

代码:

#include<bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN=105;
const int MOD=1e9+7;
int dp[MAXN][5105];
int a[MAXN],d[MAXN];
int n,m;
ll qpow(ll a,ll b)
{
	ll ret=1;a%=MOD;
	for(ll i=b;i;i>>=1,a=a*a%MOD)
	{
		if(i&1) ret=ret*a%MOD;
	}
	return ret;
}
void add(int &x,int y)
{
	x=(1LL*x+y)%MOD;
}
void solve()
{
	scanf("%d%d",&n,&m);
	int lim=d[n];
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n+1;i++)
		for(int j=0;j<=lim;j++)
			dp[i][j]=0;
	dp[0][0]=1;a[n+1]=1;
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=lim;j++)
		{
			int w;
			if(w=dp[i][j])
			{
				for(int k=i+1;k<=n+1;k++)
				{
					if(a[k]==1)
					{
						add(dp[k][j+d[k-i-1]],w);
						break;
					}
					else if(a[k]==2)
					{
						add(dp[k][j+d[k-i-1]],MOD-w);
					}
				}
			}
		}
	}
	int ans=0;
	for(int i=1;i<=lim;i++)
		add(ans,qpow(i,m)*dp[n+1][i]%MOD);
	printf("%d\n",ans);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	for(int i=1;i<=100;i++)
		d[i]=i*(i+1)>>1;
	while(T--)
	{
		solve();
	}
	return 0;
}

J - Books

 

水题(但是我不会啊。。。)

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
ll a[N],b[N];
int main()
{
    int T;
    scanf("%d",&T);
    while(T -->0)
    {
        int n,m;
        int a_len=0;
        ll tmp;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&tmp);
            if(tmp==0)
                m--;
            else
            {
                a[a_len++] = tmp;
            }
        }
        for(int i=a_len-1;i>=0;i--)
        {
            if(i==a_len-1)
                b[i] = a[i];
            else
                b[i] = min(b[i+1],a[i]);
        }
        for(int i=1;i<a_len;i++)
        {
            a[i] += a[i-1];
        }
        if(a_len==m)
        {
            printf("Richman\n");
        }
        else if(m < 0)
        {
            printf("Impossible\n");
        }
        else if(m == 0)
        {
            printf("%lld\n",b[m]-1);
        }
        else
        {
            printf("%lld\n",a[m-1]+b[m]-1);
        }
    }
    return 0;
}

L - Sub-cycle Graph

 

好像是个很牛逼的计数,队友在纸上画了一个小时搞出来的...

 

代码:

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int MAXN=100010;
const ll MOD = 1e9+7;
ll fac[MAXN],inv[MAXN];
ll f2[MAXN];
ll qpow(ll a,ll b)
{
	ll ret=1;a%=MOD;
    for(ll i=b;i;i>>=1,a=a*a%MOD)
        if(i&1) ret=ret*a%MOD;
    return ret;
}
void init()
{
	fac[0]=1;
	for(int i=1;i<MAXN;i++)//阶乘打表
	    fac[i]=fac[i-1]*i%MOD;
    for(int i=0;i<MAXN;i++)
        f2[i] = qpow(qpow(2,i),MOD-2);
    inv[0]=1;inv[MAXN-1]=qpow(fac[MAXN-1],MOD-2);//费马小定理求逆元
    for(int i=MAXN-2;i>=1;i--)
        inv[i]=inv[i+1]*(i+1)%MOD;

}
ll C(ll n,ll m)
{
    if(m>n||m<0) return 0;
    ll s1=fac[n],s2=inv[n-m]*inv[m]%MOD;
    return s1*s2%MOD;
}
int main()
{
    init();
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll n,m;
        scanf("%lld%lld",&n,&m);
        if(m==0)
        {
            puts("1");
            continue;
        }
        if(m>n)
        {
            printf("0\n");
        }
        else if(m==n)
        {
            if(n==2)
                printf("1\n");
            else
                printf("%lld\n",(fac[n-1]*f2[1]) % MOD);
        }
        else
        {
            ll ans = 0;
            for(ll i=max(0ll,n-(m*2));i<=n-(m+1);i++)
            {
                ll tmp = fac[n-i];
                ll p = C(m-1,n-i-m-1);
                tmp*=p;tmp%=MOD;

                p = inv[n-i-m];
                tmp*=p;tmp%=MOD;

                p = f2[n-i-m];
                tmp*=p;tmp%=MOD;

                //printf("i=%lld %lld\n",i,tmp);
                ans+=(tmp*C(n,i)) % MOD;
                ans%=MOD;
            }
            printf("%lld\n",ans);
        }
    }
}

M - Function and Function

 

真的水题,模拟就行了

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int judge(int x)
{
    switch(x)
    {
        case 0:return 1;
        case 1:return 0;
        case 2:return 0;
        case 3:return 0;
        case 4:return 1;
        case 5:return 0;
        case 6:return 1;
        case 7:return 0;
        case 8:return 2;
        case 9:return 1;
    }
    return 0;
}
int f(int x)
{
    if(x==0) return 1;
    int ret=0;
    while(x)
    {
        ret+=judge(x%10);
        x/=10;
    }
    return ret;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int x,k;
        scanf("%d%d",&x,&k);
        for(int i=1;i<=k;i++)
        {
            x=f(x);
            if(x==0)
            {
                int res=k-i;
                if(res%2) x=1;
                else x=0;
                break;
            }
        }
        printf("%d\n",x);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞赛)是一项面向大学生的计算机编程竞赛,涉及算法和数据结构等领域。在比赛中,选手需要解决一系列编程问题,使用合适的算法和数据结构来实现正确和高效的解决方案。 对于整理ACM-ICPC模板,以下是一些建议: 1. 了解比赛要求:首先,你需要了解ACM-ICPC比赛的具体要求和规则。这包括了解比赛所涉及的算法和数据结构,以及题目的类型和难度等。 2. 收集资料:收集与ACM-ICPC相关的资料,包括经典算法和数据结构的实现代码、常见问题的解题思路等。可以参考教材、博客、论文等资源。 3. 整理模板:将收集到的资料整理成模板。可以按照算法和数据结构的分类进行整理,例如排序算法、图算法、字符串算法等。对每个模板,添加必要的注释和示例代码,以便理解和使用。 4. 测试代码:对每个模板编写测试代码,确保它们的正确性和可靠性。可以使用已知的测试用例或自行设计测试用例。 5. 更新与扩充:定期更新和扩充模板,以适应ACM-ICPC比赛中新出现的算法和数据结构。同时,根据自己的经验和理解,对模板进行优化和改进。 6. 练习和复习:在比赛之前,利用整理好的模板进行练习和复习。尝试解决一些经典问题,使用模板中的算法和数据结构进行实现,并进行优化。 希望这些建议对你整理ACM-ICPC模板有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值