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;
}