克拉克是一名人格分裂患者。某一天克拉克转换成了一名初中生,去考化学(实在编不下去了QAQ)。 考完后克拉克发现他没有得到满分,摔!他看了一下卷子,发现一个极其傻逼的化合反应配平他配错了(心里千万只哔~在奔腾)。 他十分不爽,于是想写一个程序来完成这个问题,于是他把问题交给了你。 克拉克遇到的化合反应是这样的: 你有两种化合物,A和B,A由∣A∣种元素组成,B由∣B∣种元素组成。 已知生成物为C,且系数为1。求出A和B的系数a,b使得化合反应aA+bB=C, a,b∈N∗成立。
第一行是数据组数T(1≤T≤10). 每组数据第一行是三个整数A,B,C(1≤A,B,C≤26),分别表示∣A∣,∣B∣,∣C∣。 接下来A+B+C行,每行形如X c,分别表示A,B,C中元素X的个数为c(X为26个大写字母其中之一,保证同一物质中不会出现重复的元素,1≤c≤100)
对于每组数据,输出一行。 如果能配平,输出字典序最小的答案(a最小的情况下b最小)。否则输出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
第一组样例,取第一种物质2个第二种物质3个就能配平得到第三种物质。第二组样例,无论怎么弄,都配不出来。
官方题解:由于数目很小,我们可以直接枚举a和b。
#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: 84Submissions: 327Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/65536 K (Java/Others)官方题解:将∣xA−xB∣+∣yA−yB∣分成4种情况考虑可以知道这等价于max(∣(xA+yA)−(xB+yB)∣,∣(xA−yA)−(xB−yB)∣),所以我们维护最大最小的xA+yA和xA−yA就行了。问题描述克拉克是一名精神分裂患者。某一天克拉克变成了一位几何研究学者。 他研究一个有趣的距离,曼哈顿距离。点A(xA,yA)和点B(xB,yB)的曼哈顿距离为∣xA−xB∣+∣yA−yB∣。 现在他有n个这样的点,他需要找出两个点i,j使得曼哈顿距离最大。输入描述第一行是一个整数T(1≤T≤5),表示数据组数。 每组数据第一行为两个整数n,seed(2≤n≤1000000,1≤seed≤109),表示点的个数和种子。 n个点的坐标是这样得到的: 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#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;