- 逆序輸出
#include<stdio.h>
#define maxn 1000000
int a[maxn];
int main()
{
int x, n=0;
// 輸入
while(scanf("%d", &x) == 1)
a[n++] = x;
// 輸出
for(int i=n-1; i>=1; i--){
printf("%d ", a[i]);
}
printf("%d\n", a[0]);
return 0;
}
a[n++]
,首先賦值a[n]=x
,然後執行n=n+1
- 對於變量n,n++和++n都會給n加1,但當它們用在一個表達式中時,行爲有所差別:n++會使用加1的值計算表達式,而++n會使用加1後的值計算表達式
- 比較大的數組儘量聲明在main函數外,否則程序可能無法運行
- 開燈問題
n盞燈,第1個人把所有燈打開,第2個人按下所有編號爲2的倍數的開關(這些燈將被關掉),第3個人按下所有編號爲3的倍數的開關(其中關掉的燈將被打開,開着的燈將被關掉),依此類推。一共有k個人,問最後有哪些燈開着?
輸入n和k,輸出開着的燈的編號。k<=n<=1000。#include<stdio.h>
#include<string.h>
#define maxn 1010
int a[maxn];
int main()
{
int n, k, first = 1;
// 數組a初始化爲0
memset(a, 0, sizeof(a));
scanf("%d%d", &n, &k);
// 模擬讓每個人去按開關
for(int i=1; i<=k; i++){
for(int j=1; j<=n; j++){
if(j%i == 0){
a[j] = !a[j];
}
}
}
// 輸出
for(int i=1; i<=n; i++){
if(a[i]){
// 輸出時第一個數字前無空格
if(first){
first = 0;
}else{
printf(" ");
}
printf("%d", i);
}
}
printf("\n");
return 0;
}
memset(a, 0, sizeof(a));
的作用是把數組初始化爲0,定義在string.h中。
- 蛇形填數
在nn方陣裏填入1,2,…,nn,要求填成蛇形。n<=8。#include<stdio.h>
#include<string.h>
#define maxn 20
#define maxm 20
int a[maxn][maxm];
int main()
{
int n, x=0, y=0, tot = 0;
scanf("%d", &n);
memset(a, 0, sizeof(a));
tot = a[0][y=n-1] = 1;
// 賦值過程
while(tot < n*n)
{
// 先向下走
while(x+1<n && !a[x+1][y])
{
a[++x][y] = ++tot;
}
// 向左走
while(y-1>=0 && !a[x][y-1])
{
a[x][--y] = ++tot;
}
// 向上走
while(x-1>=0 && !a[x-1][y])
{
a[--x][y] = ++tot;
}
// 向右走
while(y+1<n && !a[x][y+1])
{
a[x][++y] = ++tot;
}
}
// 輸出
for(x=0; x<n; x++)
{
for(y=0; y<n; y++)
printf("%3d", a[x][y]);
printf("\n");
}
return 0;
}
這道題的思路值得好好思考。
- 豎式問題
#include<stdio.h>
#include<string.h>
int main()
{
int count = 0;
char s[20], buf[99];
scanf("%s", s);
for(int abc=111; abc<=999; abc++)
{
for(int de=11; de<=99; de++)
{
int x = abc*(de%10), y = abc*(de/10), z = abc*de;
sprintf(buf, "%d%d%d%d%d", abc, de, x, y, z);
// 檢查每個字符是否都在輸入的集合
int ok = 1;
for(int i=0; i<strlen(buf); i++)
{
if(strchr(s, buf[i]) == NULL)
ok = 0;
}
if(ok)
{
printf("<%d>\n", ++count);
printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n", abc, de, x, y, z);
}
}
}
printf("The number of solutions = %d\n", count);
return 0;
}
模擬豎式計算,但是必須豎式中所有的字符都必須屬於輸入的數字集合。
- 趣測試
#include<stdio.h>
#include<math.h>
int main()
{
int count = 0;
printf("%d %d %d", count++, count++, count++);
return 0;
}
- Tex中的引號
#include<stdio.h>
int main()
{
int c, q=1;
while((c = getchar()) != EOF)
{
if(c == '"')
{
printf("%s", q ? "``":"''");
q = !q;
}else{
printf("%c", c);
}
}
return 0;
}
getchar,讀取下一個字符。
- WERTUYU
輸入一個錯位後敲出的字符串,輸出打字員本來想打出的句子。輸入保證合法。#include<stdio.h>
char s[] = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./";
int main()
{
int i,c;
while((c = getchar()) != EOF)
{
for(i=1; s[i] && s[i] != c; i++);
if(s[i]){
putchar(s[i-1]);
}else{
putchar(c);
}
}
return 0;
}
- 迴文詞
輸入一個字符串,判斷它是否爲迴文串以及鏡像串。輸入字符串保證不含數字0。所謂迴文串,就是反轉以後和原串相同,如abba和madam。所有鏡像串,就是左右·鏡像之後和原串相同,如2S和3AIAE。注意,並不是每個字符在鏡像之後都能得到一個合法字符。#include<stdio.h>
#include<string.h>
#include<ctype.h>
// 每個字符的鏡像字符 A-Z 1-9
const char* rev = "A 3 HIL JM o 2TUVWXY51SE Z 8 ";
// 輸出的結果 “不是迴文串” “迴文串” “鏡像串” “鏡像迴文串”
const char* msg[] = {"not a palindrome", "a regular palindrome", "a mirrored string", "a mirrored palindrome"};
char r(char ch) {
// isalpha 判斷字符是否爲字母
if(isalpha(ch)) {
return rev[ch - 'A'];
}
return rev[ch - '0' + 25];
}
int main() {
char s[30];
while(scanf("%s", s) == 1) {
// 字符串長度
int len = strlen(s);
// 標誌
int p = 1, m = 1;
for(int i=0; i<(len+1)/2; i++) {
// 是否是迴文串
if(s[i] != s[len-1-i]) {
p = 0;
}
// 是否是鏡像串
if(r(s[i]) != s[len-1-i]) {
m = 0;
}
}
printf("%s -- is %s.\n\n", s, msg[m*2+p]);
}
return 0;
}
- 猜數字遊戲的提示
實現一個經典“猜數字”遊戲。給定答案序列和用戶猜的序列,統計有多少數字位置正確(A),有多少數字在兩個序列都出現過但位置不對(B)。#include<stdio.h>
#define maxn 1010
int main() {
int n, a[maxn], b[maxn];
int kase = 0;
while(scanf("%d", &n) == 1 && n) {
printf("Game %d:\n", ++kase);
// 輸入答案序列
for(int i =0 ; i<n; i++) {
scanf("%d", &a[i]);
}
// 處理猜測序列
for(;;) {
int A = 0, B = 0;
// 求出位置正確的數字個數A
for(int i=0; i<n; i++) {
scanf("%d", &b[i]);
if(a[i] == b[i]) A++;
}
// 當猜測序列全爲0退出
int sign = 1;
for(int i=0; i<n; i++){
if(b[i] != 0){
sign = 0;
break;
}
}
if(sign == 1) break;
// 找到兩個序列都出現過的數字個數B
for(int d=1; d<=9; d++) {
int c1 = 0, c2 = 0;
for(int i = 0; i<n; i++) {
if(a[i] == d) c1++;
if(b[i] == d) c2++;
}
if(c1<c2) B += c1;
else B += c2;
}
// 輸出結果
printf(" (%d, %d)\n", A, B-A);
}
}
return 0;
}
這裏做了一個小實驗,#include<stdio.h>
#include<math.h>
int main()
{
int count = 0;
printf("%d \n", ++count);
printf("%d \n", count);
return 0;
}
再看下面這個程序運行結果,#include<stdio.h>
#include<math.h>
int main()
{
int count = 0;
printf("%d \n", count++);
printf("%d \n", count);
return 0;
}
- 生成元
如果x加上x的各個數字之和得到y,就說x是y的生成元。給出n(1<=n<=100000),
求最小生成元。無解輸出0。例如,n=216, 121,2005時的解分別爲198,0,1979。// 一次性枚舉
#include<stdio.h>
#include<string.h>
#define maxn 100005
int ans[maxn];
int main() {
int T, n;
memset(ans, 0, sizeof(ans));
for(int m=1; m < maxn; m++){
int x = m, y = m;
// 把x的每一位與x加起來
while(x > 0){
y += x % 10;
x /= 10;
}
// 把最小的生成元保存下來
if(ans[y] == 0 || m < ans[y]){
ans[y] = m;
}
}
scanf("%d", &T);
while(T--){
scanf("%d", &n);
printf("%d\n", ans[n]);
}
return 0;
}
- 環狀序列
長度爲n的環狀串有n種表示法,分別爲從某個位置開始順時針得到。在這些表示法中,字典序最小的稱爲“最小表示”。
輸入一個長度爲n(n<=100)的環狀DNA串(只包含A、C、G、T這4種字符)的額、一種表示法,你的任務是輸出該環狀串的最小表示。#include<stdio.h>
#include<string.h>
#define maxn 105
// 比較分別以p和q爲開頭的序列
int less(const char* s, int p, int q){
int n = strlen(s);
for(int i= 0; i < n; i++){
if(s[(p+i)%n] != s[(q+i)%n]){
return s[(p+i)%n] < s[(q+i)%n];
}
}
return 0;
}
int main(){
int T;
char s[maxn];
// T個字符串
scanf("%d", &T);
// 獲取輸入、處理字符串
while(T--){
scanf("%s", s);
// 到目前爲止的標誌
int ans = 0;
// 字符串的長度
int n = strlen(s);
// 找到最小的字符
for(int i=1; i<n; i++){
if(less(s, i, ans)) ans = i;
}
// 輸出最小表示
for(int i=0; i< n; i++){
putchar(s[(i+ans)%n]);
}
putchar('\n');
}
return 0;
}