您的位置:首页 > 其它

uva 的 3 道水题

2016-04-14 11:34 197 查看
好吧我发现我走了一些弯路,两本白皮书还没看完就弄其他的去了,其实其他的也没怎么弄。现在回来补白皮书。

uva 340 猜数字游戏。

给你一个源序列(由数字0 ~ 9组成),再给你多个目标序列。让你统计两个数A和B,A是在源序列和目的序列里都出现了且位置正确的,B是在两个序列中都出现了,但是位置不正确的。

例如

1 3 5 5

1 1 2 3  A = 1, B = 1;(因为数字1在源串和目的串中都出现了且位置相同(0位置),而数字3在源串和目的串中都出现了,但是位置不同(分别是1 和 3))。

题意大概是这样(不要管1位置的数字1,因为已经有0位置的数字1满足A情况)

分析:A很好求出,但是B的话有点麻烦(而且要剔除A中的情况)。

书上的分析是:直接统计就可以得到A,为了求B,对于每个数字(1 ~ 9),统计二者出现的次数 c1 和 c2,则 min(c1, c2)就是该数字对B的贡献,最后输出的时候要减去A的部分。

的确,数据范围特别小,只是从1 ~ 9,所以这种做法是很好的(O(9 * n))。而如果要逐个比较的话,复杂度是O(n^2)并且还很容易重复计算。汝佳老师的解法的确简单。

(对了,这段时间做题目我一直尝试丢开IDE而用gvim,尝试不要单步调试而采用输出调试。。不知道有没有好处)

/*************************************************************************
> File Name: main.cpp
> Author: Triose
> Mail: Triose@163.com
> Created Time: 2016/4/13 星期三 下午 9:58:17
************************************************************************/
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
#define rep(i,a) for((i)=0; i<(a);(i)++)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define LL __int64
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b)*b; }
template<class T> inline T Min(T a, T b) { return a<b ? a : b; }
template<class T> inline T Max(T a, T b) { return a>b ? a : b; }
int n, m;
#define N 1010
int souce
;
int aim
;
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("Out.txt", "w", stdout);
#endif
int k = 0;
while(sf(n) && n) {
for(int i = 0; i < n; i++) {
sf(souce[i]);
}
printf("Game %d:\n", ++k);
for(; ;) {
int a = 0, b = 0;
for(int i = 0; i < n; i++) {
sf(aim[i]);
if(aim[i] == souce[i])
a++;
}
if(!aim[0])
break;
int tmps = 0, tmpa = 0;
for(int i = 1; i < 10; i++) {
for(int j = 0; j < n; j++) {
if(souce[j] == i)
tmps++;
if(aim[j] == i)
tmpa++;
}
b += Min(tmps, tmpa);
tmps = 0;
tmpa = 0;
// pf(b);
}
printf(" (%d,%d)\n",a,b - a);
}
}
return 0;
}


第二题, uva 1583
意思是x + (x的各位数之和) = y,那么x就是y的生成元。现在给你一个n,求它的最小生成元。1<=n <= 1e+5

分析一下就可以发现x < y,求最小生成元的过程可以采用i 从 [1, n)的循环求出,一旦满足条件输出结束。

但是这样会很慢,而题目的数据范围不是很大,数组能存下。所以可以采用O(N)的预处理和O(1)查询的方法。

但是我一开始脑子有点问题是用的O(N)的预处理和O(n)的查询。。。。不过也过了(ans [i] = i + getsum(i),意思是i是ans[i]的最小生成元,然后输入n遍历输出就行了)

后来脑子一抽发现自己神经病,既然ans[i] 能等于 i + getsum(i),为什么ans[i + getsum(i)]不能等于 i呢,这样就是O(1)查询

后来又wa了一发因为求出来的生成元并不是最小的。。。。因为后来的覆盖了。。。所以加上一句,如果ans[i] != 0 就不做任何操作。

/*************************************************************************
> File Name: main.cpp
> Author: Triose
> Mail: Triose@163.com
> Created Time: 2016/4/13 星期三 下午 10:49:15
************************************************************************/

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
#define rep(i,a) for((i)=0; i<(a);(i)++)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define LL __int64
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b)*b; }
template<class T> inline T Min(T a, T b) { return a<b ? a : b; }
template<class T> inline T Max(T a, T b) { return a>b ? a : b; }
int n, m;
#define N 100010
int ans
;
int getans(int i) {
int tmp = 0;
while(i) {
tmp += i % 10;
i /= 10;
}
return tmp;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("Out.txt", "w", stdout);
#endif
mem(ans,0);
for(int i = 1; i < N; i++) {
int tmp = i + getans(i);
if(!ans[tmp])
ans[tmp] = i;
}
/*
for(int i = 0; i < 20; i++) {
pf(ans[i]);
}
*/
int t;
sf(t);
while(t--) {
sf(n);
pf(ans
);
}
return 0;
}


uva 1584

意思是给定一个AGCT四个字母组成的字符串(环状),让你输出从某个位置开始的字典序最小的字符串。

分析:我一开始想,这尼玛加权求个sum然后如果sum< sum0就让sum0等于sum然后记录位置最后从pos开始输出就行了吗。。。后来一想sum += str[i] - 'A', sum *= 10就行了。。。后来一想,10 ^100没哪个类型能存下。。放弃。。不过当然没放弃,我想AGCT四个字母尼玛我改成4进制的加权总行了吧?果然还是存不下。。我一想 4^100次方也挺大,不行。。。。后来还是看了书上的方法。。。真是该剁手。。贴代码吧

/*************************************************************************
> File Name: main.cpp
> Author: Triose
> Mail: Triose@163.com
> Created Time: 2016/4/14 星期四 上午 10:34:12
************************************************************************/

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
#define rep(i,a) for((i)=0; i<(a);(i)++)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define enter putchar(10)
#define LL __int64
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b)*b; }
template<class T> inline T Min(T a, T b) { return a<b ? a : b; }
template<class T> inline T Max(T a, T b) { return a>b ? a : b; }
int n, m;
#define N 110
char str
;
int ans;
int len;
int pos;
int cmp(int u, int v) {
for(int i = 0; i < len; i++) {
if(str[(u + i) % len] != str[(v + i) % len])
return str[(u + i) % len] > str[(v + i) % len];
}
return 0;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("Out.txt", "w", stdout);
#endif
int _;
sf(_);
while(_--) {
sfs(str);
pos = 0;
ans = 0;
len = strlen(str);
for(int i = 1; i < len; i++) {
if(cmp(ans, i)) {
ans = i;
}
}
for(int i = 0 ; i < len; i++) {
putchar(str[(ans + i) % len]);
}
enter;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: