BestCoder Round #72 (div.2) 总结

116 篇文章 0 订阅
16 篇文章 0 订阅

Clarke and chemistry

 
 Accepts: 206
 
 Submissions: 601
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
克拉克是一名人格分裂患者。某一天克拉克转换成了一名初中生,去考化学(实在编不下去了QAQ)。  
考完后克拉克发现他没有得到满分,摔!他看了一下卷子,发现一个极其傻逼的化合反应配平他配错了(心里千万只哔~在奔腾)。  
他十分不爽,于是想写一个程序来完成这个问题,于是他把问题交给了你。  

克拉克遇到的化合反应是这样的:  
你有两种化合物,AABBAA|A|A种元素组成,BB|B|B种元素组成。  
已知生成物为CC,且系数为1。求出AABB的系数a,ba,b使得化合反应aA + bB = C,\ \ a, b \in \text{N}^*aA+bB=C,  a,bN成立。
输入描述
第一行是数据组数T(1 \le T \le 10)T(1T10).  
每组数据第一行是三个整数A, B, C(1 \le A, B, C \le 26)A,B,C(1A,B,C26),分别表示|A|, |B|, |C|A,B,C。  
接下来A+B+CA+B+C行,每行形如X\ cX c,分别表示A, B, CA,B,C中元素XX的个数为ccXX2626个大写字母其中之一,保证同一物质中不会出现重复的元素,1 \le c \le 1001c100
输出描述
对于每组数据,输出一行。  
如果能配平,输出字典序最小的答案(aa最小的情况下bb最小)。否则输出NO。
输入样例
2
2 3 5
A 2
B 2
C 3
D 3
E 3
A 4
B 4
C 9
D 9
E 9
2 2 2
A 4
B 4
A 3
B 3
A 9
B 9
输出样例
2 3
NO
Hint
第一组样例,取第一种物质22个第二种物质33个就能配平得到第三种物质。  

第二组样例,无论怎么弄,都配不出来。

官方题解:由于数目很小,我们可以直接枚举aabb

#include<stdio.h>
#include<string.h>
#include<string>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxm=101;
char a[maxm][maxm];
char b[maxm][maxm];
char c[maxm][maxm];
int a1[maxm];
int b1[maxm];
int c1[maxm];
map<int,int>q;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int A,B,C;
        scanf("%d%d%d",&A,&B,&C);
        for(int i=0;i<A;i++)
        {
            scanf("%s%d",a[i],&a1[i]);
        }
        for(int i=0;i<B;i++)
        {
            scanf("%s%d",b[i],&b1[i]);
        }
        for(int i=0;i<C;i++)
        {
            scanf("%s%d",c[i],&c1[i]);
        }
        int ok=0;
        int x=0,y=0;
        for(int i=1;i<=101;i++)
        {
            for(int j=1;j<=101;j++)
            {
                q.clear();
                for(int k1=0;k1<A;k1++)
                {
                    int o=a[k1][0]-'0';
                    q[o]+=a1[k1]*i;
                }
                for(int k1=0;k1<B;k1++)
                {
                    int o=b[k1][0]-'0';
                    q[o]+=b1[k1]*j;
                }
                int cnt=0;
                for(int k1=0;k1<C;k1++)
                {
                    int o=c[k1][0]-'0';
                    if(q[o]==c1[k1])
                        cnt++;
                    else
                        continue;
                }
                if(cnt==C)
                {
                    x=i;
                    y=j;
                    ok=1;
                    break;
                }
            }
            if(ok)
            {
                break;
            }
        }
        if(ok)
            printf("%d %d\n",x,y);
        else
            printf("NO\n");
    }
    return 0;
}

Clarke and points

 
 Accepts: 84
 
 Submissions: 327
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
克拉克是一名精神分裂患者。某一天克拉克变成了一位几何研究学者。  
他研究一个有趣的距离,曼哈顿距离。点A(x_A, y_A)A(xA,yA)和点B(x_B, y_B)B(xB,yB)的曼哈顿距离为|x_A-x_B|+|y_A-y_B|xAxB+yAyB。  
现在他有nn个这样的点,他需要找出两个点i, ji,j使得曼哈顿距离最大。  
输入描述
第一行是一个整数T(1 \le T \le 5)T(1T5),表示数据组数。  
每组数据第一行为两个整数n, seed(2 \le n \le 1000000, 1 \le seed \le 10^9)n,seed(2n1000000,1seed109),表示点的个数和种子。  

nn个点的坐标是这样得到的:

long long seed;
inline long long rand(long long l, long long r) {
	static long long mo=1e9+7, g=78125;
	return l+((seed*=g)%=mo)%(r-l+1);
}

// ...

cin >> n >> seed;
for (int i = 0; i < n; i++)
	x[i] = rand(-1000000000, 1000000000),
	y[i] = rand(-1000000000, 1000000000);
输出描述
对于每组数据输出一行,表示最大的曼哈顿距离。
输入样例
2
3 233
5 332
输出样例
1557439953
1423870062
官方题解:|x_A-x_B|+|y_A-y_B|xAxB+yAyB分成4种情况考虑可以知道这等价于max(|(x_A+y_A)-(x_B+y_B)|, |(x_A-y_A)-(x_B-y_B)|)max((xA+yA)(xB+yB),(xAyA)(xByB)),所以我们维护最大最小的x_A+y_AxA+yAx_A-y_AxAyA就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define LL __int64
const LL dem=2;
const LL maxxn=1e6+10;
const LL inf=1e18;
struct Point
{
    LL x[dem];
} p[maxxn];
LL n;
LL minx[1<<dem], maxx[1<<dem];
long long seed;
inline LL rand(LL l, LL r)
{
    static LL mo=1e9+7, g=78125;
    return l+((seed*=g)%=mo)%(r-l+1);
}
LL solve()
{
    LL i, j, k, t, tmp=1<<dem;
    LL s, ans=-inf;
    for(i=0; i<tmp; i++)
    {
        minx[i]=inf;
        maxx[i]=-inf;
    }
    for(i=0; i<n; i++)
    {
        for(j=0; j<tmp; j++)
        {
            t=j;
            s=0;
            for(k=0; k<dem; k++)
            {
                if(t&1)
                    s+=p[i].x[k];
                else s-=p[i].x[k];
                t>>=1;
            }
            if(maxx[j]<s)maxx[j]=s;
            if(minx[j]>s)minx[j]=s;
        }
    }
    for(i=0; i<tmp; i++)
    {
        if(maxx[i]-minx[i]>ans)
            ans=maxx[i]-minx[i];
    }
    return ans;
}
int main()
{
    LL t;
    scanf("%I64d",&t);
    while(t--)
    {
        LL i, j;
        scanf("%I64d%I64d",&n,&seed);
        for(i=0; i<n; i++)
        {
            p[i].x[0]=rand(-1000000000, 1000000000);
            p[i].x[1]=rand(-1000000000, 1000000000);
        }
        printf("%I64d\n", solve());
    }
    return 0;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值