• 获取Windows下某进程监听的TCP/UDP端口


    1、在Windows下用CMD netstat命令可以获得当前进程监听端口号的信息,如netstat -ano可以看到IP、port、状态和监听的PID。

    那么可以执行CMD这个进程得到监听的端口号信息,C#代码如下:

                //进程id
                int pid = ProcInfo.ProcessID;
                
                //存放进程使用的端口号链表
                List<int> ports = new List<int>();
    
                Process pro = new Process();
                pro.StartInfo.FileName = "cmd.exe";
                pro.StartInfo.UseShellExecute = false;
                pro.StartInfo.RedirectStandardInput = true;
                pro.StartInfo.RedirectStandardOutput = true;
                pro.StartInfo.RedirectStandardError = true;
                pro.StartInfo.CreateNoWindow = true;
                pro.Start();
                pro.StandardInput.WriteLine("netstat -ano");
                pro.StandardInput.WriteLine("exit");
                Regex reg = new Regex("\s+", RegexOptions.Compiled);
                string line = null;
                ports.Clear();
                while ((line = pro.StandardOutput.ReadLine()) != null)
                {
                    line = line.Trim();
                    if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
                    {
                        line = reg.Replace(line, ",");
                        string[] arr = line.Split(',');
                        if (arr[4] == pid.ToString())
                        {
                            string soc = arr[1];
                            int pos = soc.LastIndexOf(':');
                            int pot = int.Parse(soc.Substring(pos + 1));
                            ports.Add(pot);
                        }
                    }
                    else if (line.StartsWith("UDP", StringComparison.OrdinalIgnoreCase))
                    {
                        line = reg.Replace(line, ",");
                        string[] arr = line.Split(',');
                        if (arr[3] == pid.ToString())
                        {
                            string soc = arr[1];
                            int pos = soc.LastIndexOf(':');
                            int pot = int.Parse(soc.Substring(pos + 1));
                            ports.Add(pot);
                        }
                    }
                }
                pro.Close();

    2、如果不执行CMD进程,如何获得?可以参考这篇文章http://www.cnblogs.com/BoyXiao/archive/2012/02/20/2359273.html

    文章介绍了使用Windows API获得进程和端口的映射关系:

    (1)根据进程 ID 获得该进程所打开的所有的 TCP 和 UDP 端口。

    (2)根据端口号来获得打开该端口的进程。

    C语言代码如下:

    // ProcessorPort.cpp : 定义 DLL 应用程序的导出函数。
    //
    
    #include "stdafx.h"
    
    #include <Windows.h>   
    #include <Psapi.h>   
    #include <Iprtrmib.h>   
    #include <Winsock2.h>
    
    #pragma  comment(lib,"Psapi.lib")
    #pragma  comment(lib,"Iphlpapi.Lib")
    #pragma  comment(lib,"WS2_32.lib")
    
    enum TcpOrUdp
    {
        TcpType,   
        UdpType  
    };
    
    typedef struct  
    {  
        DWORD dwState;      //连接状态   
        DWORD dwLocalAddr;  //本地地址   
        DWORD dwLocalPort;  //本地端口   
        DWORD dwRemoteAddr; //远程地址   
        DWORD dwRemotePort; //远程端口   
        DWORD dwProcessId;  //进程标识 
    }MIB_TCPEXROW,*PMIB_TCPEXROW;  
    
    
    typedef struct  
    {  
        DWORD dwLocalAddr;  //本地地址   
        DWORD dwLocalPort;  //本地端口   
        DWORD dwProcessId;  //进程标识   
    
    }MIB_UDPEXROW,*PMIB_UDPEXROW;  
    
    
    typedef struct  
    {  
        DWORD dwState;      //连接状态   
        DWORD dwLocalAddr;  //本地地址   
        DWORD dwLocalPort;  //本地端口   
        DWORD dwRemoteAddr; //远程地址   
        DWORD dwRemotePort; //远程端口   
        DWORD dwProcessId;  //进程标识   
        DWORD Unknown;      //待定标识
    }MIB_TCPEXROW_VISTA,*PMIB_TCPEXROW_VISTA;  
    
    
    typedef struct  
    {  
        DWORD dwNumEntries;  
        MIB_TCPEXROW table[ANY_SIZE];
    }MIB_TCPEXTABLE,*PMIB_TCPEXTABLE;  
    
    
    typedef struct  
    {  
        DWORD dwNumEntries;  
        MIB_TCPEXROW_VISTA table[ANY_SIZE];
    }MIB_TCPEXTABLE_VISTA,*PMIB_TCPEXTABLE_VISTA;  
    
    
    typedef struct  
    {  
        DWORD dwNumEntries;  
        MIB_UDPEXROW table[ANY_SIZE];
    }MIB_UDPEXTABLE,*PMIB_UDPEXTABLE;  
    
    
    //=====================================================================================//   
    //Name: DWORD AllocateAndGetTcpExTableFromStack()                                      //                                                                //   
    //Descripion: 该函数仅仅只在 Windows XP,Windows Server 2003 下有效                    //   
    //=====================================================================================//   
    typedef DWORD (WINAPI *PFNAllocateAndGetTcpExTableFromStack)(  
        PMIB_TCPEXTABLE *pTcpTabel,  
        bool bOrder,  
        HANDLE heap,  
        DWORD zero,  
        DWORD flags  
        );  
    
    //=====================================================================================//   
    //Name: DWORD AllocateAndGetUdpExTableFromStack()                                      //   
    //Descripion: 该函数仅仅只在 XP,Windows Server 2003 下有效                            //   
    //=====================================================================================//   
    typedef DWORD (WINAPI *PFNAllocateAndGetUdpExTableFromStack)(  
        PMIB_UDPEXTABLE *pUdpTable,  
        bool bOrder,  
        HANDLE heap,  
        DWORD zero,  
        DWORD flags  
        );  
    
    //=====================================================================================//   
    //Name: DWORD InternalGetTcpTable2()                                                   //   
    //Descripion: 该函数在 Windows Vista 以及 Windows 7 下面效                             //   
    //=====================================================================================//   
    typedef DWORD (WINAPI *PFNInternalGetTcpTable2)(  
        PMIB_TCPEXTABLE_VISTA *pTcpTable_Vista,  
        HANDLE heap,  
        DWORD flags  
        );  
    
    //=====================================================================================//   
    //Name: DWORD InternalGetUdpTableWithOwnerPid()                                        //   
    //Descripion: 该函数在 Windows Vista 以及 Windows 7 下面效                             //   
    //=====================================================================================//   
    typedef DWORD (WINAPI *PFNInternalGetUdpTableWithOwnerPid)(  
        PMIB_UDPEXTABLE *pUdpTable,  
        HANDLE heap,  
        DWORD flags  
        );  
    
    
    //=====================================================================================//   
    //Name: DWORD GetProcessIdByPort()                                                     //   
    //Descripion: 根据端口号得到打开该端口号的进程ID(支持 XP,Server 2003,Vista,Win7)   //   
    //=====================================================================================//   
    extern "C" __declspec(dllexport) DWORD __stdcall GetProcessIdByPort(TcpOrUdp type, DWORD dwPort)  
    {  
        HMODULE hModule = LoadLibraryW(L"iphlpapi.dll");  
        if (hModule == NULL)  
        {  
            return 0;  
        }  
    
        if(type == TcpType)  
        {  
            // 表明查询的是 TCP 信息   
            PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;  
            pAllocateAndGetTcpExTableFromStack =   
                (PFNAllocateAndGetTcpExTableFromStack)GetProcAddress(hModule, "AllocateAndGetTcpExTableFromStack");  
            if (pAllocateAndGetTcpExTableFromStack != NULL)  
            {  
                // 表明为 XP 或者 Server 2003 操作系统   
                PMIB_TCPEXTABLE pTcpExTable = NULL;  
                if (pAllocateAndGetTcpExTableFromStack(&pTcpExTable, TRUE, GetProcessHeap(), 0, AF_INET) != 0)  
                {  
                    if (pTcpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                    }  
    
                    FreeLibrary(hModule);  
                    hModule = NULL;  
    
                    return 0;  
                }  
    
                for (UINT i = 0; i < pTcpExTable->dwNumEntries; i++)  
                {  
                    // 过滤掉数据,只查询我们需要的进程数据   
                    if(dwPort == ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort))  
                    {  
                        DWORD dwProcessId = pTcpExTable->table[i].dwProcessId;  
                        if (pTcpExTable)  
                        {  
                            HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                        }  
    
                        FreeLibrary(hModule);  
                        hModule = NULL;  
    
                        return dwProcessId;  
                    }  
                }  
    
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  
    
                FreeLibrary(hModule);  
                hModule = NULL;  
    
                return 0;  
            }  
            else  
            {  
                // 表明为 Vista 或者 7 操作系统   
                PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;  
                PFNInternalGetTcpTable2 pInternalGetTcpTable2 =   
                    (PFNInternalGetTcpTable2)GetProcAddress(hModule, "InternalGetTcpTable2");  
                if (pInternalGetTcpTable2 == NULL)  
                {  
                    if (pTcpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                    }  
    
                    FreeLibrary(hModule);  
                    hModule = NULL;  
    
                    return 0;  
                }  
    
                if (pInternalGetTcpTable2(&pTcpExTable, GetProcessHeap(), 1))  
                {  
                    if (pTcpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                    }  
    
                    FreeLibrary(hModule);  
                    hModule = NULL;  
    
                    return 0;  
                }  
    
                for (UINT i = 0;i < pTcpExTable->dwNumEntries; i++)  
                {  
                    // 过滤掉数据,只查询我们需要的进程数据   
                    if(dwPort == ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort))  
                    {  
                        DWORD dwProcessId = pTcpExTable->table[i].dwProcessId;  
                        if (pTcpExTable)  
                        {  
                            HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                        }  
    
                        FreeLibrary(hModule);  
                        hModule = NULL;  
    
                        return dwProcessId;  
                    }  
                }  
    
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  
    
                FreeLibrary(hModule);  
                hModule = NULL;  
    
                return 0;  
            }  
        }  
        else if(type == UdpType)  
        {  
            // 表明查询的是 UDP 信息   
            PMIB_UDPEXTABLE pUdpExTable = NULL;  
            PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;  
            pAllocateAndGetUdpExTableFromStack =   
                (PFNAllocateAndGetUdpExTableFromStack)GetProcAddress(hModule,"AllocateAndGetUdpExTableFromStack");  
            if (pAllocateAndGetUdpExTableFromStack != NULL)  
            {  
                // 表明为 XP 或者 Server 2003 操作系统   
                if (pAllocateAndGetUdpExTableFromStack(&pUdpExTable, TRUE, GetProcessHeap(), 0, AF_INET) != 0)  
                {  
                    if (pUdpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                    }  
    
                    FreeLibrary(hModule);  
                    hModule = NULL;  
    
                    return 0;  
                }  
    
                for (UINT i = 0; i < pUdpExTable->dwNumEntries; i++)  
                {  
                    // 过滤掉数据,只查询我们需要的进程数据   
                    if (dwPort == ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort))  
                    {  
                        DWORD dwProcessId = pUdpExTable->table[i].dwProcessId;  
                        if (pUdpExTable)  
                        {  
                            HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                        }  
    
                        FreeLibrary(hModule);  
                        hModule = NULL;  
    
                        return dwProcessId;  
                    }  
                }  
    
                if (pUdpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                }  
    
                FreeLibrary(hModule);  
                hModule = NULL;  
    
                return 0;  
            }  
            else  
            {  
                // 表明为 Vista 或者 7 操作系统   
                PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;  
                pInternalGetUdpTableWithOwnerPid =   
                    (PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, "InternalGetUdpTableWithOwnerPid");  
                if (pInternalGetUdpTableWithOwnerPid != NULL)  
                {  
                    if (pInternalGetUdpTableWithOwnerPid(&pUdpExTable, GetProcessHeap(), 1))  
                    {  
                        if (pUdpExTable)  
                        {  
                            HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                        }  
    
                        FreeLibrary(hModule);  
                        hModule = NULL;  
    
                        return 0;  
                    }  
    
                    for (UINT i = 0; i < pUdpExTable->dwNumEntries; i++)  
                    {  
                        // 过滤掉数据,只查询我们需要的进程数据   
                        if (dwPort == ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort))  
                        {  
                            DWORD dwProcessId = pUdpExTable->table[i].dwProcessId;  
                            if (pUdpExTable)  
                            {  
                                HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                            }  
    
                            FreeLibrary(hModule);  
                            hModule = NULL;  
    
                            return dwProcessId;  
                        }  
                    }  
                }  
    
                if (pUdpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                }  
    
                FreeLibrary(hModule);  
                hModule = NULL;  
    
                return 0;  
            }  
        }  
        else  
        {  
            FreeLibrary(hModule);  
            hModule = NULL;  
    
            return -1;  
        }  
    }  
    
    
    //===========================================================================================//   
    //Name: DWORD GetAllPortByProcessId()                                                        //   
    //Descripion: 根据进程ID得到该进程所打开的所有的端口号,并且在 dwAllPort 数组中返回所有端口号//   
    //            其中 dwMaxLen 为数组的长度,函数的返回值为进程所打开的端口的数目               //   
    //            (支持 XP,Server 2003,Vista,Win7)                                            //   
    //===========================================================================================//   
    extern "C" __declspec(dllexport) DWORD __stdcall GetAllPortByProcessId(TcpOrUdp type, DWORD dwProcessId, DWORD * dwAllPort, DWORD dwMaxLen)  
    {  
        DWORD dwPortCount = 0;  
        HMODULE hModule = LoadLibraryW(L"iphlpapi.dll");  
        if (hModule == NULL)  
        {  
            return dwPortCount;  
        }  
    
        if(type == TcpType)  
        {  
            // 表明查询的是 UDP 信息   
            PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;  
            pAllocateAndGetTcpExTableFromStack = (PFNAllocateAndGetTcpExTableFromStack)GetProcAddress(hModule, "AllocateAndGetTcpExTableFromStack");  
            if (pAllocateAndGetTcpExTableFromStack != NULL)  
            {  
                // 表明为 XP 或者 Server 2003 操作系统   
                PMIB_TCPEXTABLE pTcpExTable = NULL;  
                if (pAllocateAndGetTcpExTableFromStack(&pTcpExTable, TRUE, GetProcessHeap(), 0, AF_INET) != 0)  
                {  
                    if (pTcpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                    }  
    
                    FreeLibrary(hModule);  
                    hModule = NULL;  
    
                    return dwPortCount;  
                }  
    
                for (UINT i = 0; i < pTcpExTable->dwNumEntries; i++)  
                {  
                    // 过滤掉数据,只获取我们要查询的进程的 Port 信息   
                    if(dwProcessId == pTcpExTable->table[i].dwProcessId)  
                    {  
                        if(dwPortCount < dwMaxLen)  
                        {  
                            dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort);  
                            dwPortCount++;  
                        }  
                    }  
                }  
    
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  
    
                FreeLibrary(hModule);  
                hModule = NULL;  
    
                return dwPortCount;  
            }  
            else  
            {  
                // 表明为 Vista 或者 7 操作系统   
                PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;  
                PFNInternalGetTcpTable2 pInternalGetTcpTable2 = (PFNInternalGetTcpTable2)GetProcAddress(hModule, "InternalGetTcpTable2");  
                if (pInternalGetTcpTable2 == NULL)  
                {  
                    if (pTcpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                    }  
    
                    FreeLibrary(hModule);  
                    hModule = NULL;  
    
                    return dwPortCount;  
                }  
    
                if (pInternalGetTcpTable2(&pTcpExTable, GetProcessHeap(), 1))  
                {  
                    if (pTcpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                    }  
    
                    FreeLibrary(hModule);  
                    hModule = NULL;  
    
                    return dwPortCount;  
                }  
    
                for (UINT i = 0;i < pTcpExTable->dwNumEntries; i++)  
                {  
                    // 过滤掉数据,只获取我们要查询的进程的 TCP Port 信息   
                    if(dwProcessId == pTcpExTable->table[i].dwProcessId)  
                    {  
                        if(dwPortCount < dwMaxLen)  
                        {  
                            dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort);  
                            dwPortCount++;  
                        }  
                    }  
                }  
    
                if (pTcpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pTcpExTable);  
                }  
    
                FreeLibrary(hModule);  
                hModule = NULL;  
    
                return dwPortCount;  
            }  
        }  
        else if(type == UdpType)  
        {  
            // 表明查询的是 UDP 信息   
            PMIB_UDPEXTABLE pUdpExTable = NULL;  
            PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;  
            pAllocateAndGetUdpExTableFromStack = (PFNAllocateAndGetUdpExTableFromStack)GetProcAddress(hModule,"AllocateAndGetUdpExTableFromStack");  
            if (pAllocateAndGetUdpExTableFromStack != NULL)  
            {  
                // 表明为 XP 或者 Server 2003 操作系统   
                if (pAllocateAndGetUdpExTableFromStack(&pUdpExTable, TRUE, GetProcessHeap(), 0, AF_INET) != 0)  
                {  
                    if (pUdpExTable)  
                    {  
                        HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                    }  
    
                    FreeLibrary(hModule);  
                    hModule = NULL;  
    
                    return dwPortCount;  
                }  
    
                for (UINT i = 0; i < pUdpExTable->dwNumEntries; i++)  
                {  
                    // 过滤掉数据,只获取我们要查询的进程的 UDP Port信息   
                    if(dwProcessId == pUdpExTable->table[i].dwProcessId)  
                    {  
                        if(dwPortCount < dwMaxLen)  
                        {  
                            dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort);  
                            dwPortCount++;  
                        }  
                    }  
                }  
    
                if (pUdpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                }  
    
                FreeLibrary(hModule);  
                hModule = NULL;  
    
                return dwPortCount;  
            }  
            else  
            {  
                // 表明为 Vista 或者 7 操作系统   
                PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;  
                pInternalGetUdpTableWithOwnerPid = (PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, "InternalGetUdpTableWithOwnerPid");  
                if (pInternalGetUdpTableWithOwnerPid != NULL)  
                {  
                    if (pInternalGetUdpTableWithOwnerPid(&pUdpExTable, GetProcessHeap(), 1))  
                    {  
                        if (pUdpExTable)  
                        {  
                            HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                        }  
    
                        FreeLibrary(hModule);  
                        hModule = NULL;  
    
                        return dwPortCount;  
                    }  
    
                    for (UINT i = 0; i < pUdpExTable->dwNumEntries; i++)  
                    {  
                        // 过滤掉数据,只获取我们要查询的进程的 UDP Port信息   
                        if(dwProcessId == pUdpExTable->table[i].dwProcessId)  
                        {  
                            if(dwPortCount < dwMaxLen)  
                            {  
                                dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort);  
                                dwPortCount++;  
                            }  
                        }  
                    }  
                }  
    
                if (pUdpExTable)  
                {  
                    HeapFree(GetProcessHeap(), 0, pUdpExTable);  
                }  
    
                FreeLibrary(hModule);  
                hModule = NULL;  
    
                return dwPortCount;  
            }  
        }  
        else  
        {  
            FreeLibrary(hModule);  
            hModule = NULL;  
    
            return dwPortCount;  
        }  
    }  
    View Code

    如果要在.Net平台下使用,将其编译成DLL,使用PInvoke得到DLL导出函数就可以了。

    C#测试代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace ProcessorPortDllTest
    {
        public enum TcpOrUdp
        {
            TcpType,
            UdpType
        };
    
        public class ProcessPortHelper
        {
            [DllImport("ProcessorPort.dll",CallingConvention = CallingConvention.StdCall)]
            public extern static uint GetProcessIdByPort(TcpOrUdp type, uint dwPort);
    
            [DllImport("ProcessorPort.dll",CallingConvention = CallingConvention.StdCall)]
            public extern static uint GetAllPortByProcessId(TcpOrUdp type, uint dwProcessId, uint[] dwAllPort, uint dwMaxLen);
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                uint port = 1025;
                uint processorId = ProcessPortHelper.GetProcessIdByPort(TcpOrUdp.TcpType, port);
                Console.WriteLine("Port {0} is using by processor {1}",port,processorId);
    
                uint processorId1 = 1072;
    
                uint[] TcpPorts = new uint[100];
                uint count = ProcessPortHelper.GetAllPortByProcessId(TcpOrUdp.TcpType, processorId1, TcpPorts, (uint)TcpPorts.Length);
                Console.WriteLine("Processor {0} is using TCP port: ", processorId1);
                for (uint i = 0; i < count; ++i)
                {
                    Console.WriteLine(TcpPorts[i]);
                }
    
                uint[] UdpPorts = new uint[100];
                uint count1 = ProcessPortHelper.GetAllPortByProcessId(TcpOrUdp.UdpType, processorId1, UdpPorts, (uint)UdpPorts.Length);
                Console.WriteLine("Processor {0} is using UDP port: ", processorId1);
                for (uint i = 0; i < count1; ++i)
                {
                    Console.WriteLine(UdpPorts[i]);
                }
    
    Console.ReadKey(); } } }

    获得进程监听TCP/UDP端口号的DLL:ProcessorPort.rar

  • 相关阅读:
    BZOJ 2434 [NOI2011]阿狸的打字机
    BZOJ 3319 黑白树
    BZOJ 2500 幸福的道路
    BZOJ 3884 上帝与集合的正确用法
    BZOJ 3594[Scoi2014]方伯伯的玉米田
    BZOJ 3038上帝造题的七分钟2
    BZOJ 3887[Usaco2015 Jan]Grass Cownoisseur
    BZOJ 1875[SDOI2009]HH去散步
    看电影
    单峰
  • 原文地址:https://www.cnblogs.com/luxiaoxun/p/3404176.html
Copyright © 2020-2023  润新知