好吧我发现我走了一些弯路,两本白皮书还没看完就弄其他的去了,其实其他的也没怎么弄。现在回来补白皮书。
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: [email protected] > 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[N]; int aim[N]; 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; }
意思是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: [email protected] > 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[N]; 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[n]); } 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: [email protected] > 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[N]; 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; }