zoukankan      html  css  js  c++  java
  • 2018-2019_20165212_20165222_20165313《信息安全系统设计基础》实验三报告

    2018-2019 20165222《信息安全系统设计基础》实验三 并发程序

    实验三-并发程序-1

    任务详情

    1:学习使用Linux命令wc(1)

    2:基于Linux Socket程序设计实现wc(1)服务器(端口号是学号的后6位)和客户端

       客户端传一个文本文件给服务器

       服务器返回文本文件中的单词数

    3:上传代码并至少测试附件中的二个文件

    实验步骤:

    使用man -k wc查找相关命令

    继续使用man 1 wc查找相关指令

    代码展示

    client.c

    #include <netinet/in.h>    // for sockaddr_in
    #include <sys/types.h>    // for socket
    #include <sys/socket.h>    // for socket
    #include <stdio.h>        // for printf
    #include <stdlib.h>        // for exit
    #include <string.h>        // for bzero
    #include <unistd.h>
    /*
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    */
    
    #define HELLO_WORLD_SERVER_PORT    165222 
    #define BUFFER_SIZE 1024
    #define FILE_NAME_MAX_SIZE 512
    #define FILE_WORDS_NUMBER 32
    int main(int argc, char **argv)
    {
       if (argc != 2)
       {
           printf("Usage: ./%s ServerIPAddress
    ",argv[0]);
           exit(1);
       }
    
       //设置一个socket地址结构client_addr,代表客户机internet地址, 端口
       struct sockaddr_in client_addr;
       bzero(&client_addr,sizeof(client_addr)); //把一段内存区的内容全部设置为0
       client_addr.sin_family = AF_INET;    //internet协议族
       client_addr.sin_addr.s_addr = htons(INADDR_ANY);//INADDR_ANY表示自动获取本机地址
       client_addr.sin_port = htons(0);    //0表示让系统自动分配一个空闲端口
       //创建用于internet的流协议(TCP)socket,用client_socket代表客户机socket
       int client_socket = socket(AF_INET,SOCK_STREAM,0);
       if( client_socket < 0)
       {
           printf("Create Socket Failed!
    ");
           exit(1);
       }
       //把客户机的socket和客户机的socket地址结构联系起来
       if( bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr)))
       {
           printf("Client Bind Port Failed!
    "); 
           exit(1);
       }
    
       //设置一个socket地址结构server_addr,代表服务器的internet地址, 端口
       struct sockaddr_in server_addr;
       bzero(&server_addr,sizeof(server_addr));
       server_addr.sin_family = AF_INET;
       if(inet_aton(argv[1],&server_addr.sin_addr) == 0) //服务器的IP地址来自程序的参数
       {
           printf("Server IP Address Error!
    ");
           exit(1);
       }
       server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
       socklen_t server_addr_length = sizeof(server_addr);
       //向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接
       if(connect(client_socket,(struct sockaddr*)&server_addr, server_addr_length) < 0)
       {
           printf("Can Not Connect To %s!
    ",argv[1]);
           exit(1);
       }
    
       char file_name[FILE_NAME_MAX_SIZE+1];
       bzero(file_name, FILE_NAME_MAX_SIZE+1);
       printf("Please Input File Name On Server:	");
       scanf("%s", file_name);
       
       char buffer[BUFFER_SIZE];
       bzero(buffer,BUFFER_SIZE);
       strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name));
       //向服务器发送buffer中的数据
       send(client_socket,buffer,BUFFER_SIZE,0);
    
       FILE * fp = fopen(file_name,"r");
       if(NULL == fp )
       {
           printf("File:	%s Not Found
    ", file_name);
           exit(1);
       }
       else
       {
               bzero(buffer, BUFFER_SIZE);
               int file_block_length = 0;
               while( (file_block_length = fread(buffer,sizeof(char),BUFFER_SIZE, fp))>0)
               {
                   //printf("file_block_length = %d
    ",file_block_length);
                   //发送buffer中的字符串到服务器
                   if(send(client_socket,buffer,file_block_length,0)<0)
                   {
                       printf("Send File:	%s Failed
    ", file_name);
                       break;
                   }
                   bzero(buffer, BUFFER_SIZE);
               }
       }
       
       printf("Send File:	 %s To Server[%s] Finished
    ",file_name, argv[1]);
    
       printf("The File has %d words.
    ", wc_func(file_name));
       fclose(fp);
     
       //关闭socket
       close(client_socket);
       return 0;
    }
    int wc_func(char *file_name)
    {
    int t;
    int w = 0;
    int state = 0;
    FILE *in;
    if((in = fopen(file_name,"r"))==NULL)
    {
    printf("wc %s:no this file or dir
    ",file_name);
    return;
    }
    while((t=fgetc(in))!=EOF)
    {
    
    if(t=='
    '||t==' '||t=='
    ') {
               	state = 0;
               	continue;
           	} else {
               	if(state == 0) {
                   	state = 1;
                   	w++;
              }
               	continue;
           	}
    }
    return w;
    }
    

      serve.c

    #include <netinet/in.h>    // for sockaddr_in
    #include <sys/types.h>    // for socket
    #include <sys/socket.h>    // for socket
    #include <stdio.h>        // for printf
    #include <stdlib.h>        // for exit
    #include <string.h>        // for bzero
    #include <unistd.h>
    /*
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    */
    #define HELLO_WORLD_SERVER_PORT    165222 
    #define LENGTH_OF_LISTEN_QUEUE 20
    #define BUFFER_SIZE 1024
    #define FILE_NAME_MAX_SIZE 512
    #define FILE_WORDS_NUMBER 32
    int wc_func(char *file_name);
    int main(int argc, char **argv)
    {
        //设置一个socket地址结构server_addr,代表服务器internet地址, 端口
        struct sockaddr_in server_addr;
        bzero(&server_addr,sizeof(server_addr)); //把一段内存区的内容全部设置为0
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = htons(INADDR_ANY);
        server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
    
        //创建用于internet的流协议(TCP)socket,用server_socket代表服务器socket
        int server_socket = socket(PF_INET,SOCK_STREAM,0);
        if( server_socket < 0)
        {
            printf("Create Socket Failed!");
            exit(1);
        }
        
        //把socket和socket地址结构联系起来
        if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))
        {
            printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT); 
            exit(1);
        }
        
        //server_socket用于监听
        if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) )
        {
            printf("Server Listen Failed!"); 
            exit(1);
        }
        while (1) //服务器端要一直运行
        {
            //定义客户端的socket地址结构client_addr
            struct sockaddr_in client_addr;
            socklen_t length = sizeof(client_addr);
    
            //接受一个到server_socket代表的socket的一个连接
            //如果没有连接请求,就等待到有连接请求--这是accept函数的特性
            //accept函数返回一个新的socket,这个socket(new_server_socket)用于同连接到的客户的通信
            //new_server_socket代表了服务器和客户端之间的一个通信通道
            //accept函数把连接到的客户端信息填写到客户端的socket地址结构client_addr中
            int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
            if ( new_server_socket < 0)
            {
                printf("Server Accept Failed!
    ");
                break;
            }
            
        char file_name[FILE_NAME_MAX_SIZE+1];
        bzero(file_name, FILE_NAME_MAX_SIZE+1);
        char buffer[BUFFER_SIZE];
        bzero(buffer,BUFFER_SIZE);
        recv(new_server_socket,file_name,BUFFER_SIZE,0);
        
        
        FILE * fp = fopen(file_name,"w");
        if(NULL == fp )
        {
            printf("File:	%s Can Not Open To Write
    ", file_name);
            exit(1);
        }
        
        //从客户端接收数据到buffer中
        bzero(buffer,BUFFER_SIZE);
        int len = 0;
        while( len = recv(new_server_socket,buffer,BUFFER_SIZE,0))
        {
            if(len < 0)
            {
                printf("Recieve Data From Client %s Failed!
    ", argv[1]);
                break;
            }
    
            int write_length = fwrite(buffer,sizeof(char),len,fp);
            if (write_length<len)
            {
                printf("File:	%s Write Failed
    ", file_name);
                break;
            }
            bzero(buffer,BUFFER_SIZE);    
        }
        printf("File:	%s Transfer Finished!
    ",file_name);
        
        fclose(fp);
        
        //关闭与客户端的连接
        close(new_server_socket);
        }
        //关闭监听用的socket
        close(server_socket);
        return 0;
    }
    

      

    运行截图

    实验三-并发程序-2

    任务详情

    • 使用多线程实现wc服务器并使用同步互斥机制保证计数正确
    • 上方提交代码
    • 下方提交测试
    • 对比单线程版本的性能,并分析原因

    代码展示

    serve.c

    #include<netinet/in.h>                         // for sockaddr_in  
    #include<sys/types.h>                          // for socket  
    #include<sys/socket.h>                         // for socket  
    #include<stdio.h>                              // for printf  
    #include<stdlib.h>                             // for exit  
    #include<string.h>                             // for bzero  
      
    #define HELLO_WORLD_SERVER_PORT       165222
    #define BUFFER_SIZE                   1024  
    #define FILE_NAME_MAX_SIZE            512  
    int mywc(char file_name[],int choose);
    int main(int argc, char **argv)  
    {  
        FILE *fp;
        if (argc != 2)  
        {  
            printf("Usage: ./%s ServerIPAddress
    ", argv[0]);  
            exit(1);  
        }  
    
    // 设置一个socket地址结构client_addr, 代表客户机的internet地址和端口  
        struct sockaddr_in client_addr;  
        bzero(&client_addr, sizeof(client_addr));  
        client_addr.sin_family = AF_INET; // internet协议族  
        client_addr.sin_addr.s_addr = htons(INADDR_ANY); // INADDR_ANY表示自动获取本机地址  
        client_addr.sin_port = htons(0); // auto allocated, 让系统自动分配一个空闲端口  
    
    // 创建用于internet的流协议(TCP)类型socket,用client_socket代表客户端socket  
        int client_socket = socket(AF_INET, SOCK_STREAM, 0);  
        if (client_socket < 0)  
        {  
            printf("Create Socket Failed!
    ");  
            exit(1);  
        }  
    
    // 把客户端的socket和客户端的socket地址结构绑定   
        if (bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)))  
        {  
            printf("Client Bind Port Failed!
    ");  
            exit(1);  
        }  
    
    // 设置一个socket地址结构server_addr,代表服务器的internet地址和端口  
        struct sockaddr_in  server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
    
    // 服务器的IP地址来自程序的参数   
        if (inet_aton(argv[1], &server_addr.sin_addr) == 0)  
        {  
            printf("Server IP Address Error!
    ");  
            exit(1);  
        }                                                                                                               
        server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
        socklen_t server_addr_length = sizeof(server_addr);  
        // 向服务器发起连接请求,连接成功后client_socket代表客户端和服务器端的一个socket连接  
        if (connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length) < 0)  
        {  
            printf("Can Not Connect To %s!
    ", argv[1]);  
            exit(1);  
        }  
    
        char file_name[FILE_NAME_MAX_SIZE + 1];  
        bzero(file_name, sizeof(file_name));  
        printf("Please Input File Name.	");  
        scanf("%s", file_name);  
        if((fp = fopen(file_name,"r"))==NULL)
        {
             printf("Failure to open %s
    ",file_name);
             exit(0);
        }
        
        char buffer[BUFFER_SIZE];  
        bzero(buffer, sizeof(buffer));  
        strcpy(buffer,file_name);
        if(send(client_socket,buffer,BUFFER_SIZE,0)==-1)
        {
            printf("发送文件名失败
    ");
        }
        char ch;
        int i=0;
        while((ch=fgetc(fp))!=EOF)
        {
            buffer[i++]=ch;
            if(i>=BUFFER_SIZE)
            {
                if((send(client_socket, buffer, BUFFER_SIZE, 0))==-1)
                {
                    printf("发送文件失败
    ");
                }
                bzero(buffer, sizeof(buffer));
                i=0;
            }
        }
        if(i<BUFFER_SIZE)
        {
            if((send(client_socket, buffer, i, 0))==-1)
            {
                printf("发送文件失败
    ");
            }
        }
        printf("发送%s完毕
    ",file_name);
        mywc(file_name,1);
         mywc(file_name,2);
        // 向服务器发送buffer中的数据,此时buffer中存放的是客户端需要接收的文件 
        //以下接收服务器发来的单词个数
        bzero(buffer, sizeof(buffer));
    //  int length = 0;  
    /*  int length = recv(client_socket, buffer, sizeof(buffer), 0);
          
            if (length < 0)  
            {  
                printf("Recieve Data From Server %s Failed!
    ", argv[1]);   
            }  
            else
            {
            printf("Recieve words number %c From Server[%s] Finished!
    ",buffer[0],argv[1]);
    
            }
            bzero(buffer, BUFFER_SIZE);  */
    // 传输完毕,关闭socket   
        
        fclose(fp);  
        close(client_socket);  
        return 0;  
    
    }  
     int mywc(char file_name[],int choose)
      {
           FILE *fp;
           char ch;
            int flag=0,num=0;
            // int choose;
            //  printf("统计单词个数还是实现“wc -w”?(1or2)
    ");
              // scanf("%d",&choose);
                if((fp = fopen(file_name,"r"))==NULL)
                 {
                      printf("Failure to open %s
    ",file_name);
                       exit(0);
                    }
                 
                      if(choose==1)
                       {
                        while((ch=fgetc(fp))!=EOF)
                         {
                              if(ch==' ' || ch=='
    ' || ch=='	' ||  ch=='!' || ch=='?' || ch=='"' || ch=='.' || ch== '\,' || ch==':' || ch=='(' || ch==')' || ch==';'     || ch=='-')
                              {
                              flag=0;
                              }
                              else
                              {
                              if(flag==0)
                              {
                              flag=1;
                              num++;
                              }
                              
                              }
    
                        }
    
                    }
                    else if(choose==2)
                    {
                        while((ch=fgetc(fp))!=EOF)
                        {
                            if(ch==' ' || ch=='
    ' || ch=='	' || ch=='
    ')
                            flag=0;
                            else
                            {
                                if(flag==0)
                                {
                                    flag=1;
                                    num++;
                                }
                            }
                        }
                    }
                    printf("单词个数为:%d_用方式%d计算
    ",num,choose);
                    fclose(fp);
                    return num;
    }
    
    
    #include<netinet/in.h>   
    #include<sys/types.h>   
    #include<sys/socket.h>   
    #include<stdio.h>   
    #include<stdlib.h>   
    #include<string.h>   
    #include<pthread.h>  
    #define HELLO_WORLD_SERVER_PORT    155312  
    #define LENGTH_OF_LISTEN_QUEUE     20  
    #define BUFFER_SIZE                1024  
    #define FILE_NAME_MAX_SIZE         512  
    void *process_client(void *new_server_socket);
    int mywc(char file_name[])
    {
        char ch;
        int flag=0,num=0;
        int choose;
        FILE *fp;
        printf("统计单词个数还是实现“wc -w”?(1or2)
    ");
        scanf("%d",&choose);
        if((fp = fopen(file_name,"r"))==NULL)
        {
            printf("Failure to open %s
    ",file_name);
            exit(0);
        }
    
        if(choose==1)
        {
        while((ch=fgetc(fp))!=EOF)
        {
            if(ch==' ' || ch=='
    ' || ch=='	' ||  ch=='!' || ch=='?' || ch=='"' || ch=='.' || ch== '\,' || ch==':' || ch=='(' || ch==')' || ch==';' || ch=='-')
            {
                flag=0;
            }
            else
            {
                if(flag==0)
                {
                    flag=1;
                    num++;
                }
    
            }
                       
        }
    
        }
        else if(choose==2)
        {
            while((ch=fgetc(fp))!=EOF)
            {
                if(ch==' ' || ch=='
    ' || ch=='	' || ch=='
    ')
                    flag=0;
                else
                {
                    if(flag==0)
                    {
                        flag=1;
                        num++;
                    }
                }
            }
        }
        printf("单词个数为:%d
    ",num);
        fclose(fp);
        return num;
    }
    int main(int argc, char **argv)  
    {  
    // set socket's address information   
    // 设置一个socket地址结构server_addr,代表服务器internet的地址和端口  
        struct sockaddr_in   server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
        server_addr.sin_addr.s_addr = htons(INADDR_ANY);  
        server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
    // create a stream socket   
    // 创建用于internet的流协议(TCP)socket,用server_socket代表服务器向客户端提供服务的接口  
        int server_socket = socket(PF_INET, SOCK_STREAM, 0);  
        if (server_socket < 0)  
        {  
            printf("Create Socket Failed!
    ");  
            exit(1);  
        }  
    
    // 把socket和socket地址结构绑定   
        if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))  
        {  
            printf("Server Bind Port: %d Failed!
    ", HELLO_WORLD_SERVER_PORT);  
            exit(1);  
        }  
    
    // server_socket用于监听   
        if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))  
        {  
            printf("Server Listen Failed!
    ");  
            exit(1);  
        }  
    // 服务器端一直运行用以持续为客户端提供服务   
          
        while(1)
        {
    // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept  
    // 接受此请求,同时将client端的地址和端口等信息写入client_addr中  
            struct sockaddr_in client_addr;  
            socklen_t length = sizeof(client_addr);  
    
    // 接受一个从client端到达server端的连接请求,将客户端的信息保存在client_addr中  
    // 如果没有连接请求,则一直等待直到有连接请求为止,这是accept函数的特性,可以  
    // 用select()来实现超时检测   
    // accpet返回一个新的socket,这个socket用来与此次连接到server的client进行通信  
    // 这里的new_server_socket代表了这个通信通道  
            int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);  
            printf("连接到客户端
    ");
            if (new_server_socket < 0)  
            {  
                printf("Server Accept Failed!
    ");  
                  
            }
            //添加进程相关代码
            pthread_t pid;
            if(pthread_create(&pid, NULL, process_client,(void *) &new_server_socket) < 0){
                  printf("pthread_create error
    ");
            }
            
        }
    //  close(server_socket);
    }
    void *process_client(void *new_server_socket)
    {
            int sockid=*(int *)new_server_socket;
            FILE *fp;
            //接受来自客户端的文件
            char buffer[BUFFER_SIZE]; 
            char file_name[FILE_NAME_MAX_SIZE];
            bzero(buffer, sizeof(buffer));  
            int length=0;
            if(recv(sockid,buffer,BUFFER_SIZE, 0)==-1)
            {
                printf("接受文件名%s失败
    ",buffer);
            }
            strcpy(file_name,buffer);
            strcat(file_name,"-server");
            if((fp = fopen(file_name,"w"))==NULL)
            {
                printf("Failure to open %s
    ",file_name);
                exit(0);
            }
            while( length = recv(sockid, buffer, BUFFER_SIZE, 0))
            {
                if(length<0)
                {
                    printf("接受文件出错
    ");
                    exit(0);
                }
                
                if(fwrite(buffer,sizeof(char),length,fp)<length)
                {
                    printf("写文件失败
    ");
                }
                bzero(buffer, BUFFER_SIZE);
            }
            fclose(fp);
            printf("接受文件完毕
    ");
            int number=0;
            number=mywc(file_name);
            bzero(buffer, BUFFER_SIZE);  
            buffer[0]=number+48;
    // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端  
            /*if (send(new_server_socket, buffer, sizeof(buffer), 0) < 0)  
            {  
                printf("Send number Failed!
    ");  
                 
            }  
            printf("发送单词个数完毕
    ");*/
            bzero(buffer, sizeof(buffer));  
            
    //      fclose(fp);  
            printf("File Transfer Finished!
    ");    
            close(new_server_socket);  
    } 
    

      client.c

    #include <stdio.h>
    #include <fcntl.h>
    #include <pthread.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #define PORT 165222
    #define BUFF_SIZE 1024
    #define LISTEN_SIZE 20
    typedef struct{
        char type;
        char data[BUFF_SIZE];
    }m_package;
    
    int main(){
        //创建连接
        int sock_fd = connect_tcp("127.0.0.1", PORT);
        if(-1 == sock_fd)
            return -1;
    
        m_package pac;
        int fd, cur = 0, count = 0;
        long filesize = 0;
        while(1){
            //打开文件
            memset(&pac, 0, sizeof(pac));
            pac.type = 1;
            // strcpy(pac.data, "/home/SKZH/a.txt");
            scanf("%s", pac.data);
            //获取文件信息
            struct stat sfile;
            stat(pac.data, &sfile );
            filesize = sfile.st_size;
            time_t t;
            long begin = time(&t);
            cur = count = 0;
    
            fd = open(pac.data, O_RDONLY);
            if(-1 == fd){
                printf("file open error
    ");
                continue;
            }
            //读取文件并发送
            //发送文件名
            strcpy(pac.data, strrchr(pac.data, '/') + 1);
            write(sock_fd, &pac, sizeof(pac));
            memset(&pac, 0, sizeof(pac));
    
            //发送文件长度
            pac.type = 4;
            sprintf(pac.data,"%ld",filesize);
            write(sock_fd, &pac, sizeof(pac));
            memset(&pac, 0, sizeof(pac));
    
            int read_len = 0;
            while((read_len = read(fd, pac.data, BUFF_SIZE)) > 0){
                pac.type = 2;
                write(sock_fd, &pac, sizeof(pac));
                memset(&pac, 0, sizeof(pac));
                cur += read_len;
                if(count++ % 5000 == 0){
                    count = 0;
                    printf("send to server : %.1lf\%
    ", cur * 100.0 / filesize);
                }
            }
    
            //发送结束标记
            memset(&pac, 3, sizeof(pac));
            write(sock_fd, &pac, BUFF_SIZE + 1);
            close(fd);
    
            printf("send to server : 100.0\%
    ");
            printf("file size : %d B
    ", filesize);
            printf("time : %ld ms
    ", time(&t) - begin);
            printf("send file success
    ");
            printf("------------------------
    ");
        }
        close(sock_fd);
    }
    int connectsock(char* server_ip, int server_port, int type){
        int sock_fd = socket(AF_INET, type, 0);
        if(-1 == sock_fd){
            printf("create socket error
    ");
            return -1;
        }
    
        struct sockaddr_in server_addr;
        //设置服务器地址
        bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        server_addr.sin_port = htons(server_port);
        inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
    
        //连接服务器
        if(-1 == connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in))){
            printf("connect server error
    ");
            return -1;
        }
    
        printf("connect server success
    ");
        return sock_fd;
    }
    
    int connect_tcp(char* server_ip, int server_port){
        return connectsock(server_ip, server_port, SOCK_STREAM);
    }
    
    int connect_udp(char* server_ip, int server_port){
        return connectsock(server_ip, server_port, SOCK_DGRAM);
    }
    

      

    运行截图

  • 相关阅读:
    USACO 3.3 A Game
    USACO 3.3 Camelot
    USACO 3.3 Shopping Offers
    USACO 3.3 TEXT Eulerian Tour中的Cows on Parade一点理解
    USACO 3.3 Riding the Fences
    USACO 3.2 Magic Squares
    USACO 3.2 Stringsobits
    USACO 3.2 Factorials
    USACO 3.2 Contact
    USACO 3.1 Humble Numbers
  • 原文地址:https://www.cnblogs.com/20165222lixu/p/9978470.html
Copyright © 2011-2022 走看看