ECNU OJ 3031 二进制倒置

给定一个整数 n(0≤n≤10100)、将 n 的 334 位二进制表示形式(不包括开头可能的值为 0 的位,n=0 表示为 1 位 0)前后倒置,输出倒置后的二进制数对应的整数。

例如:n=10,其二进制表示为 (330 个 0)1010,倒置后为 0101,对应输出就是 5。

Input

第 1 行:一个整数 T (1T10) 为问题数。

接下来共 T 行整数,对应每个问题有 1 行,表示 n。

Output

对于每个问题,输出一行问题的编号(0 开始编号,格式:case #0: 等)。

然后对应每个问题在一行中输出结果。

#include <stdio.h>
#include <string.h>
typedef struct  {
    int cnt, v[101];
} BIGINT;

void DIV2(BIGINT *n)
{
    int carry = 0, i; //carry为进位
    if ( n->v[n->cnt -1] < 2) n ->cnt--, carry = 1;  //若最高位为1,
    for (i = n->cnt -1; i>= 0; i--) {				//从第二位开始
        int t = 10 * carry + n->v[i];	//加上上一位余数			
        n->v[i] = t/2; //每一位除以2
        carry = t%2; //余数作为下一位进位
    }
}

void MUL2ADD(BIGINT *n, int d)
{
    int carry=d, i;
    for (i = 0; i < n->cnt; i++){
        int t=carry + n->v[i] * 2; //每一位乘以2,并处理进位
        n->v[i] = t % 10; //若该数超过10,求个位数,否则就是该数本身
        carry = t / 10;	  //余数作为下一位进位
    }
    if (carry > 0) n->v[n->cnt++] = carry; //若循环完之后,carry大于0,进位
    
}

int main(void)
{
char line[102];
int i;
BIGINT n;
scanf("%sx", line);
n.cnt = strlen(line);
for ( i = 0; i < n.cnt; i++ ){
    n.v[i] = line[n.cnt - i - 1] - '0'; //数字倒置
    
}

int s[334], cnt = 0;
while (n.cnt > 0) 
    s[cnt++] = n.v[0] %2; //数字模2
    DIV2(&n);			  //数字除以2
}

for (i = 0; i < cnt; cnt++ ){
    MUL2ADD(&n, s[i]);
}

if (n.cnt == 0) n.cnt++; //若输入为0,做额外处理
for (i = n.cnt-1; i>=0; i--){
    printf("%d".n.v[i];
}
printf('\n');
}

 

ECNU OJ 2822 内存显示

一个 int 类型变量或 double 类型变量在连续几个字节的内存中存放。读取数值时,当数值中包含小数点时类型为 double,否则类型为 int。将读入的数值存放在 int 类型变量或 double 类型变量中。以十六进制格式(a-f 字母采用小写形式)输出相应变量的连续的每个字节的值。

读入的数据保证能在一个 int 类型或 double 类型变量中正确存放。

注意:int 类型变量和 double 类型变量所占字节数以及一个变量的几个字节的存放顺序与所用计算机的体系结构和编译系统有关。

Input

每一行包含一个数值

Output

每行对应一个数据,每个字节后面都要输出一个空格

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void solveint(int n);
void solvedouble(double d);

int main()
{
    char s[31];
    while (~scanf("%s",s)){
        if (strchr(s,'.') == 0)
                solveint(atoi(s));
        else 
            solvedouble(atof(s));
        return 0;
    }
}

void solveint(int n)
{
    int c = sizeof(n);
    unsigned char *p=(unsigned char*) &n;
    while (c--)
        printf("%02x", *p++);
    putchar('\n');
}

void solvedouble(int d)
{
    int c = sizeof(d);
    unsigned char *p=(unsigned char*) &d;
    while (c--)
        printf("%02x", *p++);
    putchar('\n');
}

 

ECNU OJ 2893 数据密度

所有类型的数据在内存中都是以二进制的形式存放的。其中有些位是 1,而有些位是 0。例如:字符 A 的二进制表示 01000001 中有 2 位是 1,6 位是 0。设 sizeof(char) 为 1。

数据密度定义为一块内存数据中 1 的位的占比。

写程序计算一组字符的数据密度。

Input

第 1 行:整数 n (1n10)

第 2 行 ~ n+1 行:每行是个数范围为 1 ~ 120 的一组字符。一组字符中可能包含空格、制表符、汉字、字母、数字、标点符号。

Output

对于每一行中的一组字符,以最简分数形式在一行中输出其数据密度。

分数格式:分子 / 分母

#include <stdio.h>
#include <string.h>
void solve(char *s);
int gcd(int a, int b){
    return a ? gcd(b % a, a) : b ;
}

int main ()
{
    int T;
    scanf("%d", &T);
    while(T--){
        char s[121];
        gets(s);
        solve(s);
        return 0; 
    }
}

void solve(char *s)
{
    int s1  = 0, bytes=strlen(s), i, j;
    for (int i = 0; i < bytes; i++){
        unsigned char c= s[i]; //为了使用逻辑右移,定义为无符号字符类型
        for (j = 0; j < 8; j++){
            s1 += c % 2; //统计1的位数
            c>>=1; //逻辑右移
        }
    }
    int g = gcd(s1, bytes * 8);//最大公约数
    printf ("%d/%d", s1/g, bytes * 8 / g);

}

 

ECNU OJ 3059 极坐标排序

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

struct point
{
   double x, y;
   double p, angle;
};

struct point s[1000];

int cmp (const void * a, const void *b)
{
    struct point p1, p2;
    p1 = *(struct point *)a;
    p2 = *(struct point *)b;
    
    if (p1.angle > p2.angle) return 1;				//极角大的排在后
    else if (fabs( p1.angle - p2.angle ) < 1e-10)   //极角相同
        if (p2.p > p1.p )return 1;                  //按极径大的放在前
    return -1;
}
int main (void)
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++){
    scanf( "%lf%lf", &s[i].x, &s[i].y);
    s[i].p  = sqrt ( s[i].x * s[i].x + s[i].y * s[i].y ); //计算极径
    int t;
    t = atan2( s[i].y, s[i].x );                          //计算极径的反正切
    if (t < 0 ) s[i].angle = 2 * M_PI + t;				  //由于atan2()返回值为(-π,π],所以要把负值加2π
    else s[i].angle = t;								  //正值不变
    qsort ( s, n ,sizeof(s[0]), cmp );
    for (int i=0; i<n; i++)
        printf("(%.4f,%.4f)\n", s[i].p, s[i].angle);
}
}

 

ECNU OJ 3055 字符频率

设 26 个英文字母,每个字母都对应一个使用频率,同一个字母的大小写使用频率相同。

现给定一个由 26 个英文字母构成的字符串,请将字符串按照字母使用频率由大到小重排,使用频率大的字母排在前面,使用频率小的字母排在后面,如果使用频率相同则按照字母顺序表排列,小写字母排在大写字母前面,即 a->A->b->B->c->C-d->D->……->z->Z。

例如 :

26 个字母的使用频率如下表 :

A(a) B(b) C(c) D(d) E(e) F(f) G(g) H(h) I(i) J(j) K(k) L(l) M(m)
8.19 1.47 3.83 3.91 12.25 2.26 1.71 4.57 7.10 0.14 0.41 3.77 3.34
N(n) O(o) P(p) Q(q) R(r) S(s) T(t) U(u) V(v) W(w) X(x) Y(y) Z(z)
7.06 7.26 2.89 0.09 6.85 6.36 9.41 2.58 1.09 1.59 0.21 1.58 0.08

字符串 “Thisisaexample” 重排后为 “eeTaaiisshlmpx”

字符串 “AertrtsaBereDET” 重排后为 “eeeEttTaArrrsDB”。

Input

第 1 行:一个整数 T (1≤T≤10) 为问题数。

对于每个问题,有 2 行数据,按如下格式输入:

第 1 行输入 26 个浮点数,分别表示 26 个英文字母 A(a)~Z(z) 的使用频率;

第 2 行输入一个字符串,字符串长度不超过 100 个字符,字符串由 26 个英文字母构成。

Output

对于每个问题,输出一行问题的编号(0 开始编号,格式:case #0: 等)。

然后对应每个问题在一行中输出重排后的字符串。

#include <stdio.h>
#include <algorithm>
double p[27];

int cmp(const void * a, const void * b)
{
    char ch1, ch2; //待比较字符
    int p1, p2; //p1,p2 为ch1, ch2 在字母表中的序号
    ch1=*((char *)a);
    ch2=*((char *)b);
    if (ch1 >= 'a' && ch1 <= 'z') p1 = ch1 - 'a'; else p1 = ch1 - 'A';
    if (ch2 >= 'a' && ch2 <= 'z') p1 = ch2 - 'a'; else p2 = ch2 - 'A';
    
    if(p[p1] < p[p2])  return -1; // 按字母频率排序
    else if (p[p1] == p[p2])      // 字母使用频率相同
        if (p1 == p2)
            return ch2 - ch1; //相同字母,降序排列,即小写在大写前面
        else return p1 - p2; //不同字母,但使用频率相同,按字母表顺序排列
    else return 1;

}

int main (void)
{
    for (int i =0; i < 26; i++)
        scanf("%lf",&p[i]);
    char str[101];
    scanf("%s", str);
    
    qsort(str, strlen(str),sizeof(str[0]), cmp);
    printf("%s\n", str);
}

 

ECNU OJ 3036 按数据中1的位数排序

所有数据在内存中都是以二进制形式存放的,其中有一些位是 1,而另一些位是 0。

例如,整数 100 的二进制表示为 1100100,其中 1 的位数是 3;整数 15 的二进制表示为 1111,其中 1 的位数是 4;整数-15 的 64 位二进制表示为 1111111111111111111111111111111111111111111111111111111111110001,其中 1 的位数是 61。

现在有 N 个整数,要求按照 64 位二进制补码表示中 1 的位数从大到小进行排序。若两个数的二进制表示中 1 的位数相同,则按照数本身值由小到大排序。

例如:数 100,15,0,30,7,-15,100,-100 排序后的结果为 :

-15,-100,15,30,7,100,100,0。

Input

第 1 行:整数 T (1T10) 为问题数

第 2 行:第一个问题中的 N(1≤N≤10000)

第 3 行:N 个待排序的数 (-1018≤数≤1018),每两个数之间由一个空格分隔。

第 4 ∽T*2+1 行:后面问题的数据,格式与第一个问题相同。

Output

对于每个问题,输出一行问题的编号(0 开始编号,格式:case #0: 等),然后在一行中输出排序后的数。格式为:以一个空格分隔每两个数。最后一个数后面没有空格。

#include 
#include 
#include 
struct data
{
    long long int a; //整数
    int number; //64位二进制补码中1的位数
};

int cmp (const void *a, const void *b)
{
    struct data d1, d2;
    d1 = *((struct data *)a);
    d2 = *((struct data *)b);
    if (d2.number != d1.number)
        return d2.number - d1.number; //降序排列
    else{
        if (d1.a < d2.a) // 因为cmp返回值为int 而 a为long long 所以不能直接相减 
            return -1;
        else 
            return 1;
    }
}
int main (void)
{   
    int n;
    struct data p[1000];
    scanf("%d", &n);
    for (int i = 0; i < n; i++){
        scanf("%I64d", &p[i].a);
        int d=1;
        p[i].number = 0;
        for (int t=0; t<64;t++){
            if(p[i].a & d)
                p[i].number++;
            d = d << 1;
        }
    }
    int i;
    qsort(p,n, sizeof(p[0]), cmp);
    for (i = 0; i < n - 1; i++)
        printf("%I64d ",p[i].a);
    printf("%l64d\n",p[i].a);
}

 

ECNU OJ 2947 行数据的排序

有 N 行数据,每行有若干数量不等的整数组成。现在要对这 N 行数据排序。排序原则为:首先比较行中的第一个数的值,将第一个数大的行排在前面;若第一个数相等的话,则按照第二个数的值排序(若某行没有第二个数,则该行排在后面);若第二个数还是相等的话,则比较第三个数,依次类推。

例如:

14 38 11 89

27 34

27 12 34

27

92 2 3 1

17 2

排序的结果为:

92 2 3 1

27 34

27 12 34

27

17 2

14 38 11 89

Input

第 1 行:整数 T (1T10) 为问题数

第 2 行:第一个问题的整数 N (1≤N≤1000)

第 3 ∽ N+2 行:第一个问题的每行的数据 ai 和表示行结束的标志-1, 1≤数据个数≤50。0≤ai≤10^9, 数据之间由一个空格分隔。

后面是第 2 ∽ T 个问题的数据。格式与第一个问题相同。

Output

对于每个问题,输出排序后的结果。

格式为:每行输出一行数据,数据之间有一个空格。

#include <stdio.h>

int line_data[1000][51];

//首先比较行中第一个数的值,将第一个数大的行排在前边
//如果第一个数相等,按照第二个数的值排序
//若某行没有第二个数的话,该行排在后边
//如果第二个数还是相等,则比较第三个数,以此类推

int cmp(cont void *a, const void *b)
{
    int *s1 = (int *a);
    int *s2 = (int *b);
    while (*s1 != -1 && s2 != -1 && *s1 = *s2){ //若相等比较下一个,
                                                //若不等,跳出循环
                                                //若为-1,亦跳出循环
        s1++;
        s2++;
    }
    return *s2 - *s1; //跳出循环后,降序排列

}
int main(void)
{
    int n;
    scanf("%d", &n);
    for ( int k = 0; k < n; k++ ){
        int j = 0;
        while(scanf("%d", &line_data[k][j]) && line_data[k][j] != -1){
            j++;
        }        
    }

    qsort(line_data,n, sizeof(line_data[0]), cmp);
    for (int k =0; k < n; k++){
        for ( int j = 0; line_data[k][j+1] != -1; j++ )
            printf("%d ", line_data[k][j]);
        printf("%d", line_data[k][j]);
    }

}

 

ECNU OJ 2896 随机排序

给定一组以一个空格分隔的只含大小写字母的字符串。与普通字典序不同,按照给定的字母顺序对这组字符串排序。设两个字符串的字母不会完全相同。如:Hat、hat、HAt 等不会同时出现。

例如:字母顺序为 QWERTYUIOPASDFGHJKLZXCVBNM 时,一组字符串 hat cat bat book bookworm Dallas Austin Houston fire firefox fumble 的排序结果为:Austin Dallas fumble fire firefox Houston hat cat book bookworm bat。

Input

每组数据由 2 行组成,第 1 行为字母顺序(26 个大写字母),第 2 行是需要排序的一组字符串(只含大小写字母,长度不大于 20)。

数据不多于 100 组。需要排序的一组字符串中包含的字符串个数至少 1 个,至多 100 个。

Output

对于每一组数据,输出排序后的字符串。字符串之间输出一个空格,最后一个字符串后面没有空格,而是输出一个换行符。

#include <stdio.h>

int p[26];
//按给定的字母循序对字符串排序,如果第一个字符相等,则比较第二个字符

int cmp (const void *a, const void *b)
{
    char *s1, *s2; //s1,s2用来遍历字符串
    char ch1, ch2; //ch1,ch2用来指向对应的大写字母
    s1 = (char *)a; 
    s2 = (char *)b;

//--------------------------------重要---------------------------------
    while (*s1 && *s2){
        ch1 = (*s1) >= 'a' ? *s1 - 'a' + 'A' : *s1; // 转化为大写
        ch2 = (*s2) >= 'a' ? *s2 - 'a' + 'A' : *s2; 

        if (p[ch1-'A'] != p[ch2-'A'])   //字符不相等,按顺序表比较
            return p[ch1-'A'] - p[ch2-'A']; //升序
        else { //字符相等,进入下个字符比较
            s1++; s2++;
        }

        if (*s1 == 0) //第一个字符串结束,而第二个未结束则,第一个字符串在前
            return -1;
        else          //第一个字符串未结束,而第二个结束,第一个字符串在后
            return 1;
//--------------------------------重要---------------------------------
    }
}


int main(void)
{

    char s[27];

    while(~scanf("%s\n",s)){   //读入字母顺序表
        for (int i = 0; i < 26; i++)
            p[s[i]-'A'] = i;
        
        char str[2200];
        char a[100][21];

        gets(str);
        int count = 0;
        int i = 0;
//--------------------------------重要---------------------------------
        while (true){ //根据空格分割出每个字符串,把字符串存储在二维数组
            int j = 0;
            while (str[i]!= ' ' && str[i])
                a[count][j++] = str[i++];
            a[count][j] = '\0';
            count++;  //统计字符串个数
            if (!str[i])
                break;
            else
                i++;
        }
//--------------------------------重要---------------------------------
        qsort(a, count, sizeof(a[0]), cmp);
        // qsort(首地址,排序的字符创个数,每一个数组元素大小,比较函数)
        for (int i = 0; i < count - 1; i++)
            printf("%s ", a[i]);
        printf("%s\n", a[i]);
    }
}

 

 

qsort函数和sort函数

先说明一下qsort和sort,只能对连续内存的数据进行排序,像链表这样的结构是无法排序的。

首先说一下, qsort
qsort(基本快速排序的方法,每次把数组分成两部分和中间的一个划分值,而对于有多个重复值的数组来说,基本快速排序的效率较低,且不稳定)。集成在C语言库函数里面的的qsort函数,使用 三 路划分的方法解决排序这个问题。所谓三路划分,是指把数组划分成小于划分值,等于划分值和大于划分值的三个部分。

具体介绍:-^^

void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )
int compare (const void *elem1, const void *elem2 ) );

qsort(即,quicksort)主要根据你给的比较条件给一个快速排序,主要是通过指针移动实现排序功能。排序之后的结果仍然放在原来数组中。
参数意义如下:
第一个参数 base 是 需要排序的目标数组名(或者也可以理解成开始排序的地址,因为可以写&s[i]这样的表达式)
第二个参数 num 是 参与排序的目标数组元素个数
第三个参数 width 是单个元素的大小(或者目标数组中每一个元素长度),推荐使用sizeof(s[0])这样的表达式
第四个参数 compare 就是让很多人觉得非常困惑的比较函数啦。

我们来简单讨论compare这个比较函数(写成compare是我的个人喜好,你可以随便写成什么,比如 cmp 什么的,在后面我会一直用cmp做解释)。 典型的compare的定义是int compare(const void *a,const void *b);
返回值必须是int,两个参数的类型必须都是const void *,那个a,b是随便写的,个人喜好。假设是对int排序的话,如果是升序,那么就是如果a比b大返回一个正值,小则负值,相等返回0,其他的依次类推,后面有例子来说明对不同的类型如何进行排序。

qsort 的使用方法:

一、对int类型数组排序

int num[100];

int cmp ( const void *a , const void *b )

{

  return *(int *)a - *(int *)b;  //升序排序

//return *(int *)b - *(int *)a; //降序排序

/*可见:参数列表是两个空指针,现在他要去指向你的数组元素。所以转型为你当前的类型,然后取值。
        升序排列时,若第一个参数指针指向的“值”大于第二个参数指针指向的“值”,则返回正;若第一个参数指针指向的“值”等于第二个参数指针指向的“值”,则返回零;若第一个参数指针指向的“值”小于第二个参数指针指向的“值”,则返回负。
        降序排列时,则刚好相反。

*/

}

qsort(s,n,sizeof(s[0]),cmp);
//示例完整函数(已在 VC6.0上运行通过):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int s[10000],n,i;
int cmp(const void *a,const void *b)
{
return(*(int *)b-*(int *)a);  //实现的是升序排序
}
int main()
{

// 输入想要输入的数的个数
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&s[i]);
qsort(s,n,sizeof(s[0]),cmp);
for(i=0;i<n;i++)
printf("%d ",s[i]);
return(0);
}

再说说 sort (常用于 C++ )

sort 使用时得注明:using namespace std; 或直接打 std::sort() 还得加上 #include <algorithm> 头文件

//例:

#include<iostream>
#include<algorithm>
using namespace std;



int main()
{
       int a[20];
   for(int i=0;i<20;++i)
              cin>>a[i];
     sort(a,a+20);             //范围,很明显这里是a+20 注意,这是必要的,如果是a+19
       for(i=0;i<20;i++)        //最后一个值a[19]就不会参与排序。
              cout<<a[i]<<endl;
       return 0;

}

std::sort是一个改进版的qsort. std::sort函数优于qsort的一些特点:对大数组采取9项取样,更完全的三路划分算法,更细致的对不同数组大小采用不同方法排序。

最后,我们来说说sort、qsort的区别:
sort是qsort的升级版,如果能用sort尽量用sort,使用也比较简单,不像qsort还得自己去写 cmp 函数,只要注明 使用的库函数就可以使用,参数只有两个(如果是普通用法)头指针和尾指针;

默认sort排序后是升序,如果想让他降序排列,可以使用自己编的cmp函数

#include<iostream>
#include<algorithm>
using namespace std;
int cmp(int a,int b)
{
  if(a<b)
  return 1; //升序排列,如果改为 a >b,则为降序,要注意sort()中cmp()的返值只有1和0,不像qsort中存在-1!!!!
  else
  return 0;
}


int main(){
    int i;
 int a[20];
 for(int i=0;i<5;++i)
  cin>>a[i];

sort(a,a+5,cmp);          //范围,很明显这里是a+5 注意,这是必要的,如果是a+4最后一个值a[4]就不会参与排序。
for(i=0;i<5;i++)       

cout<<a[i]<<endl;
    system("pause");
 return 0;
}

 

对二维数组的排序:
#include <iostream>
#include <algorithm>
#include <ctime>
using namespace std;

bool cmp(int *p,int *q)
{
    if(p[0]==q[0])
    {
        if(p[1]==q[1])
        {
            return p[2]<q[2];
        }
        else return p[1]<q[1];
    }
    else return p[0]<q[0];
}
int main()
{
    srand(time(0));
    int i;
    int **a=new int*[1000];
    for(i=0;i<1000;++i)
    {
        a[i]=new int[3];
        a[i][0]=rand()%1000;
        a[i][1]=rand()%1000;
        a[i][2]=rand()%1000;
        //printf("%d\t%d\t%d\n",a[i][0],a[i][1],a[i][2]);
    }
    sort(a,a+1000,cmp);
    /*cout<<"After sort"<<endl;
    for(i=0;i<1000;++i)
    {
        printf("%d\t%d\t%d\n",a[i][0],a[i][1],a[i][2]);
    }*/
    return 0;
}

 

刘汝佳第三章习题

3-1 得分 (UVa 1585)

题目:有一个客观的测试结果,如“OOXXOXXOOO”,一个“O”表示一个问题的正确答案,一个“X”表示一个错误的答案。这个测试的每个问题的分数是由它自己计算的,例如,第10个问题的得分是3,它是由它自己和它的前两个连续的O得到的。
因此,“OOXXOXXOOO”的分数是由“1 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 2 + 3”计算得到的10。
你要编写一个计算测试结果分数的程序。

提示:用一个flag标记是否是O开头

#include <iostream>
using namespace std;

int main(void)
{
    string str;
    cin >> str;
    int len = str.length();
    bool start = false;
    int count = 0;
    int sum = 0;
    for (int i = 0; i < len; i++){
        if (str[i] == 'O'){
            start = true;
            count++;
        } else if (str[i] == 'X') {
            start = false;
            count = 0;
        }
        if (start) {
            sum += count;
        }
    }
}

3-2分子量 (UVa 1586)

题目大意:给出一种物质的分子式(不带括号),求分子量。本题中分子式只包含4种原子,分别为C、H、O、N,

原子量分别为12.01,1.008,16.00,14.01

提示:用数组保存四种原子的分子量,用flag标记当前位是字母还是数字。如果是数字,超过一位的,把每一位的数值从字符串中提取出来。用数组保存每一位的分子量。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
float ans[100];
float mass[] = {12.01, 1.008, 16.00, 14.01};
char str[10];
int len;
int num(int pos, int len)//pos为数字开始的位置,len为分子式长度
{
    int temp;
    for (int i=pos;i<len;i++){ //获取数字长度,并存储到temp
        if(isdigit(str[i])){
            temp=i;
        } else {
            break;
        }
    }

    int n = 0;
    for (int i=pos; i <=temp;i++){ //根据每一十进制位计算分子量
        n = n * 10 +  (str[i] - '0');
    }
    return n - 1; //注意减一是因为最后计算的时候,字母本身占一倍 
  
}

int main(void)
{
    int flag = 0; 
    scanf("%s", str);
    len = strlen(str);
    for (int i = 0; i < len; i++){
        if (str[i] == 'C'){
            ans[i]=mass[0];
        }
        if (str[i] == 'H'){
            ans[i]=mass[1];
        }
        if (str[i] == 'O'){
            ans[i]=mass[2];
        }
        if (str[i] == 'N'){
            ans[i]=mass[3];
        }
        if(isdigit(str[i])&&flag==0){ //初始状态flag = 0,直接进入if判断 
            ans[i]=ans[i-1] * num (i, len); //若该位为数字,则计算数字乘以前面元素的分子量
            flag = 1; //做标记,表示计算数字,下次循环忽略此if判断
        } 
        if (isalpha(str[i])){ //若该位为字母,则标记flag = 0复位,方便下次循环进入上面if判断
            flag = 0;
        }
    }
    
    float sum = 0;
    for (int i = 0; i<len;i++){
       sum+=ans[i];
    }
    printf("%.3f\n",sum);
    return 0;
}

3-3 数数字(UVa1225)

题意:
把前n(n<=10000)个整数顺次写在一起,如n=15时,123456789101112131415
计算0-9各出现了多少次(输出10个数,分别是数字0-9出现的次数)
#include <iostream>
using namespace std;

int main(void)
{
    int sum[10] = {}; //sum[i]表示数字i的个数
    for (int i = 1; i <= 10000; i++){
        int j = i;
        while (j > 0){
            int k;
            k = j % 10; //获取个位
            sum[k]++;   //个位数字的个数加一
            j /= 10;    //下一位
        }
    }

    for  (int i = 0; i < 10; i++){
        cout << i <<  "  : "  << sum[i] << endl;
    }
}

3-4周期串(UVa455)

题目:求一个串的最小循环节。

解题思路:

对一个字符串求其最小周期长度,那么,最小周期长度必定是字符串长度的约数,即最小周期长度必定能被字符串长度整除

其次,对于最小周期字符串,每位都能对应其后周期字串的每一位,

 

if(a[j]!=a[j%3])说明不对应,不是周期,进行下一位扫描。

#include  <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

using namespace std;

char str[104];

int main(void)
{
    int n;
    while (~scanf("%d",&n))
        while (n--){
            scanf("%s", str);
            int len = strlen(str);
            for(int k, i = 1; i < len; i++){
                if (len % i == 0 ) //若子串长度能够整除母串
                    for (k = i; k < len; k++) //开始匹配
                        if (str[i] != str[k%i]) //如果不能匹配
                            break; //则跳出
                if (len == i) {//若全部匹配 
                    cout << i;
                    break;
                }
            }
            if (n) cout << endl;
    }
}

3-8 循环小数(UVa202)

大致题意
输入整数a(0<=a<=3000)和 b (1<=b<=3000),输出a/b的循环小数表示以及循环字节长度。例如a=5,b=43,小数表示为0.(116279069767441860465),循环字节长度为21

#include<stdio.h>  
#include<cstring>  
#include<algorithm>  
#include <iostream>
#define HardBoy main()  
#define ForMyLove return 0;  
using namespace std;  
const int MYDD = 1103+1e4;  
  
int HardBoy {  
    int quotient[MYDD];  
    int remainder[MYDD];  
    int u[MYDD];  
    int n, m, t;  
      
    while(scanf("%d %d", &n, &m) != EOF) {  
        t = n;/*3000以内*/  
        memset(quotient, 0, sizeof(quotient));  
        memset(u, 0, sizeof(u));  
        int cnt = 0;  
        quotient[cnt++] = n/m;  
        n %= m;
        //n为余数,循环前数组u[]被置0,!u[n]为真,进入循环
        while(!u[n] && n) { //u[n] == 0 

            //debug:cout << "before n= " << n << endl;
            u[n] = cnt;
            //一开始数组u[n] = cnt == 0,!u[n]为真,持续循环
            //之后cnt > 0,每次循环,u[n]被赋正值
            //直到循环至n重复出现,即出现循环节,这时u[n]已经被赋值为正值,!u[n]为假,跳出循环
            //debug:cout << "u[n]= " << cnt <<endl;
            remainder[cnt] = n;  //记录余数
            //debug:cout << "reamainder= " << n << endl;
            quotient[cnt++] = 10*n/m;  //记录商
            //debug:cout << "quotient= " << 10*n/m << endl;
            n = 10*n%m;  
            //debug:cout << "after n= " << n << endl;

            //debug:cout << endl; 
        }  
  
        printf("%d/%d = %d.", t, m, quotient[0]);  
        for (int i = 1 ; i < cnt && i <= 50 ; i++) {  
            if (n && remainder[i] == n) printf("(");  
            /*存在循环节->开始存在余数相同的位置*/  
            printf("%d",quotient[i]);  
        }  
        if (!n) printf("(0");
        //余数为零
        if (cnt > 50) printf("...");  
        printf(")\n");  
        printf("   %d = number of digits in repeating cycle\n\n",!n? 1:cnt-u[n]);  
  
    }  
    ForMyLove  
}

3-9 子序列(UVa 10340)

题意:给两个字符串A 和 B。 如果在B中能找到非连续字串和A匹配输出 YES 不能输出NO。
思路B一个个字母遍历过去每对应上A的一个字母就找A的下一个字母直到结束。。

#include <stdio.h>  
#include <string.h>  
  
char a[100005], b[100005];  
int main() {  
    while (~scanf("%s%s", a, b)) {  
        int star = 0, lenb = strlen(b), lena = strlen(a);  
        for (int i = 0; i < lenb; i ++) {  
            if (a[star] == b[i])  
                star ++;  
            if (star == lena) {  
                printf("Yes\n");  
                break;  
            }  
        }  
        if (star != lena)  
            printf("No\n");  
    }  
    return 0;  
}