1.排序(permutation)
用1,2,3...9这9个数字组成3个三位数abc,def,ghi,每个数字恰好用一次,要求: abc:def:ghi = 1:2:3.
输出所有的解.提示:不必太动脑筋.
算法思想:确定满足比例关系的3个三位数是否是由9个不同的数组成.可以分离这3个三位数的每一位,用一个长度为>=9的数组标记.假设有数字122;
则数组s[1] = s[2] = 1;类推,可知,若3个三位数由9个不同的数组成,则数组 s[1..9]每一位都为1,即测试s数组元素都为1,或者如果有0则判定不满足条件
#include<iostream> using namespace std; void permutation() { int s[10]; int x, y, z; int i, sum; // 987/3 = 329, x最大为329即可 for(x = 123; x <= 329; x++) { memset(s,0,sizeof(s)); y = 2 * x; z = 3 * x; s[x/100] = s[x/10%10] = s[x%10] = 1; s[y/100] = s[y/10%10] = s[y%10] = 1; s[z/100] = s[z/10%10] = s[z%10] = 1; bool m = true; for (i = 1; i < 10; i++) if(s[i] == 0) { m = false; break; } if(m == false ) continue; printf("%d %d %d\n", x, y, z); } } int main() { permutation(); return 0; }
2.最长回文字串(忽略大小写,会略空格和标点符号)
算法:从一点向两个方向搜,如果遇到不相等的则停止,而且还要区分区间是偶数还是奇数
#include<stdio.h> #include<string.h> #include<ctype.h> #define MAXN 5000 + 10 char buf[MAXN], s[MAXN]; //测试数据 buf[MAXN]="Confuciuss asy: Madam,I'm Adam" int p[MAXN]; int pos; int main() { int n, m = 0, max = 0; int i, j, k; fgets(buf, sizeof(s), stdin); n = strlen(buf); for(i = 0; i < n; i++) //排除其中的非字母的放在数组S中,p[m]=i; 在s中第m个对应buf中第i个 if(isalpha(buf[i])) { p[m] = i; s[m++] = toupper(buf[i]); } int begin,end; int cnt = 0; for(int i = 0; i < m; ++i) { begin = i -1; end = i + 1; cnt = 1; while(begin >= 0 && end < m && s[begin] == s[end]) //奇数个 { cnt+=2; --begin; ++end; } if(cnt > max) { max = cnt; pos = begin + 1; } begin = i; end = i+1; cnt = 0; while(begin >=0 && end < m && s[begin] == s[end]) //偶数个 { cnt+=2; --begin; ++end; } if(cnt > max) { max = cnt; pos = begin + 1; } } printf("max = %d\n", max); for(int i = p[pos]; i <= p[pos+max-1]; ++i) printf("%c",buf[i]); return 0; }
3.周期串
如果一个字符串可以由某个长度k的字符重复多次得到,我们说该串以k为周期。例如: abcabcabcabc以3为周期(注意,它以6和12为周期)。输入一个长度不超过80的串,输出它的最小周期。
样例输入:HoHoHo
样例输出:2
#include<cstdio> #include<cstring> using namespace std; int main() { char s[80+10]; int k; scanf("%s",s); k = strlen(s); bool p; for(int i = 1; i <= k; ++i) { p = true; for(int j = i; j < k; ++j) if(s[j] != s[j%i]) { p = false; break; } if(p) { printf("%d\n",i); break; } } return 0; }
4.计算两个整数在相加时需要多少次进位。输出两个0为停止。
样例输入:
123 456
555 555
123 594
0 0
样例输出:
0
3
1
#include<cstdio> using namespace std; int main() { int n,m; while(scanf("%d %d",&n,&m) == 2) { if( n == 0 && m == 0) break; int cnt = 0; int c = 0; while(n || m) { c = (n % 10 + m % 10 + c) > 9 ? 1 : 0; cnt += c; n /= 10; m /= 10; } printf("%d\n",cnt); } return 0; }
5.n的阶乘,n<=1000。
#include<cstdio> #include<cstring> using namespace std; const int maxn = 3000; int f[maxn]; int main() { memset(f,0,sizeof(f)); int i,j; int n; scanf("%d",&n); f[1] = 1; for(i = 2; i <= n; ++i) { int c = 0, s = 0; for(j = 1; j < maxn; ++j) { s = f[j] * i + c; f[j] = s % 10; c = s / 10; } } for(j = maxn -1; j >= 1; --j) if(f[j]) break; for(i = j; i >= 1; --i) printf("%d",f[i]); printf("\n"); return 0; }
6. 智力题 设置全局变量。
任务1定义int a,b要求在依次执行a=f()和b=f()后a和b的值不同。
任务2定义int a,b要求在依次执行a=(f()+g())+h()和b=f()+(g()+h())后a和b的值不同
注意:依次依次。
#include <stdio.h> int c=1; int f() { c++; return c; } int g() { c++; return c; } int h() { c++; return c; } int main() { int a,b; a =f(); b =f(); printf("a = %d, b = %d\n",a,b); } /* int main() { int a,b; a = f() + f() + h(); b = f() + (f() + h()); printf("a = %d, b = %d\n",a,b); } */
7.高精度运算类bign
#include<cstdio> #include<iostream> using namespace std; class bign { private: enum{maxn = 200}; int len, s[maxn]; public: bign(); bign(int num); bign(const char * str); bign operator =(int num); bign operator =(const char * str); string str() const; bign operator +(const bign & b) const; bign operator -(const bign & b); bign operator +=(const bign & b); bign operator -=(const bign & b); void clean(); bign operator *(const bign & b); bool operator <(const bign & b) const; bool operator <=(const bign & b) const; bool operator >(const bign & b) const; bool operator >=(const bign & b) const; bool operator ==(const bign & b) const; bool operator !=(const bign & b) const; }; bign::bign() { memset(s,0,sizeof(s)); len = 0; } bign::bign(int num) { *this = num; } bign::bign(const char * str) { *this = str; } bign bign::operator=(int num) { bign(); char s[maxn]; sprintf(s,"%d",num); *this = s; return *this; } bign bign::operator=(const char *str) { bign(); len = strlen(str); for(int i = 0; i < len; ++i) s[i] = str[len -i - 1] - '0'; return *this; } string bign::str() const { string res = ""; for(int i = 0; i < len; ++i) res = (char)(s[i] + '0') + res; if(res == "") res = "0"; return res; } bign bign::operator +(const bign & b) const { bign c; for(int i = 0, g = 0; g || i < max(len,b.len); ++i ) { int x = g; if(i < len) x += s[i]; if(i < b.len) x += b.s[i]; g = x / 10; c.s[c.len++] = x % 10; } return c; } bign bign::operator -(const bign & b) { if(*this < b) { cout << "the result is nagive/n"; return bign(); } bign c; c.len = 0; for(int i = 0, g = 0; i < len; ++i) { int x = s[i] - g; if(i < b.len) x -= b.s[i]; if(x < 0) { x += 10; g = 1; } else g = 0; c.s[c.len++] = x; } c.clean(); return c; } bign bign::operator +=(const bign & b) { *this = *this + b; return *this; } bign bign::operator -=(const bign & b) { *this = *this - b; return *this; } void bign::clean() { while(len > 0 && s[len - 1] == 0) --len; } bign bign::operator *(const bign & b) { bign c; c.len = len + b.len; for(int i = 0; i < len; ++i) for(int j = 0; j < b.len; ++j) c.s[i+j] = s[i] * b.s[j]; for(int k = 0; k < c.len; ++k) { c.s[k+1] += c.s[k] / 10; c.s[k] %= 10; } c.clean(); return c; } bool bign::operator <(const bign & b) const { if(len != b.len) return len < b.len; for(int i = 0; i < len; ++i) if(s[i] != b.s[i]) return s[i] < b.s[i]; return false; } bool bign::operator <=(const bign & b) const { return !(*this > b); } bool bign::operator >(const bign & b) const { if(len != b.len) return len > b.len; for(int i = 0; i < len; ++i) if(s[i] != b.s[i]) return s[i] > b.s[i]; return false; } bool bign::operator >=(const bign & b) const { return !(*this < b); } bool bign::operator ==(const bign & b) const { return !(b < *this) && !(*this < b); } bool bign::operator !=(const bign & b) const { return (b < *this) || (*this < b); } istream & operator >> (istream & in, bign & x) { string res; in >> res; x = res.c_str(); return in; } ostream & operator << (ostream & out, const bign & x) { out << x.str(); return out; }
8.Cantor数表
题目描述
如下数列,前5项分别是1/1,1/2,2/1,3/1,2/2……。输入n,输出第n项。
1/1 1/2 1/3 1/4 1/5
2/1 2/2 2/3 2/4
3/1 3/2 3/3
4/1 4/2
5/1
样例输入
3
14
7
12345
样例输出
2/1
2/4
1/4
59/99
【算法】
首先要看懂题目是按什么规律来排数的,首先是按斜线,然后,是一条斜线从上到下,另一条斜线从下到上交错的。
然后分析第i条斜线有i个数,前i条斜线一共有S(k)=1+2+3+···+k=k(k+1)/2个数。
n在哪条斜线上呢?只要找到一个最小的正整数k,使得n<=S(k),那么n就是第k条斜线上的第或倒数第S(k)-n+1个元素。
第k条斜线的第i个元素是i/(k+1-i),倒数第i个元素是(k+1-i)/i。
#include<stdio.h> int main() { int n; while(scanf("%d",&n) == 1) { int k = 1, s = 1; while( n > s) { ++k; s += k; } if(k % 2 == 1) printf("%d/%d",s-n+1,k+n-s); else printf("%d/%d",k+n-s,s-n+1); } return 0; }
9.因子和阶乘
输入正整数n(2<=n<=100),把阶乘n!=1*2*3*...*n分解成素因子相乘的形式,从小到大输出各个素数(2、3、5...)的指数。例如,5! 表示为 3,1, 1个2, 3, 5。程序忽略比最大素因子更大的素数(否则末尾会有无穷多个0)。
样例输入:
5
53
样例输出:
5! = 3 1 1
53! = 49 23 12 8 4 4 3 2 2 1 1 1 1 1 1 1
[分析]
因为a^m * a^n = a^(m+n),所以我们只需把所有素因子对应的指数累加起来 。注意,n<=100,即这些素因子不会超过100。我们首先构造一张最大素数为100的素数表,然后用阶乘的每一个数(从小到大)与每一个素数相模,并记录每一个素数的指数。用一个数组p来保存对应的各个素数的指数个数,并标记最大的那个素因子的下标为maxp,最后循环输出到最大下标即可。
#include<stdio.h> #include<string.h> int is_prime(int n) { for(int i = 2; i*i <= n; i++) if(n % i == 0) return 0; return 1; } int prime[100], count = 0; int main() { int n, p[100]; for(int i = 2; i <= 100; i++) if(is_prime(i)) prime[count++] = i; while(scanf("%d", &n) == 1) { printf("%d! =", n); memset(p, 0, sizeof(p)); int maxp = 0; for(int i = 1; i <= n; i++) { int m = i; for(int j = 0; j < count; j++) while(m % prime[j] == 0) { m /= prime[j]; p[j]++; if(j > maxp) maxp = j; } } for(int i = 0; i <= maxp; i++) printf(" %d", p[i]); printf("\n"); } return 0; }
10.黑白图像
输入一个n×n的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数。如果两个黑格子有公共边或者公共顶点,就说它们属于同一个八连块。如下图所示的图形有3个八连块。
输入
第1行输入一个正整数n(n≤700),此后输入n行,每行是由n个0或1组成的字符串。
输出
在输入黑白图像中,八连块的个数
样例输入
6
100100
001010
000000
110000
111000
010100
样例输出
3
#include<stdio.h> #include<string.h> const int MAXN = 700 + 10; int mat[MAXN][MAXN],vis[MAXN][MAXN]; void dfs(int x, int y) { if(!mat[x][y] || vis[x][y]) return; vis[x][y] = 1; dfs(x-1,y-1); //左上 dfs(x-1,y);//正上 dfs(x-1,y+1);//右上 dfs(x,y-1);//左边 dfs(x,y+1);//右边 dfs(x+1,y-1);//左下 dfs(x+1,y);//正下 dfs(x+1,y+1);//右下 } int main() { memset(mat,0,sizeof(mat)); memset(vis,0,sizeof(vis)); int n; FILE *fp; fp = fopen("6.4.1.txt","r"); fscanf(fp,"%d",&n); for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) fscanf(fp,"%1d",&mat[i][j]); int count = 0; for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) { if(!vis[i][j] && mat[i][j]) { ++count; dfs(i,j); } } printf("%d\n",count); return 0; }