3 条题解

  • 0
    @ 2025-11-27 15:25:53
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int n,q;
        cin>>n>>q;
        int book[1001];
        int len[1001];
        int code[1001];
        for(int i=0;i<n;i++){
            cin>>book[i];
        }
        for(int i=0;i<q;i++){
            cin>>len[i]>>code[i];
        }
        //数据读取完毕
        //先把图书编码递增排序,方便找到最小的
        sort(book,book+n);
        vector<int> p;//保存10的幂,p[i]表示10的i次方,避免重复计算
        p.push_back(1);
        for(int i=1;i<=9;i++){
            p.push_back(p[i-1]*10);
        }
        for(int i=0;i<q;i++){
            //遍历图书,找到读者需要的图书里编码最小的(先找到的第一个)
            int j=0;
            for(j=0;j<n;j++){
                if(book[j]%p[len[i]]==code[i]){
                    cout<<book[j]<<endl;
                    break;
                }
            }
            //如果遍历完都没有找到,输出-1
            if(j==n){//注意这里为啥要这个判断,j为什么要声明在for外面?
                cout<<"-1"<<endl;
            }
        }
    }
    
    • 0
      @ 2025-11-27 14:58:37

      你好!我是你的OI教练。

      这道题(NOIP 2017 普及组 T2)是一道非常典型的模拟/枚举题目。

      数据范围 N,Q1000N, Q \le 1000,这意味着我们可以接受 O(N×Q)O(N \times Q) 的复杂度,也就是对于每一个读者,把所有书都检查一遍,计算机完全跑得过来。

      下面是解题的几个关键突破口:

      1. 核心逻辑:如何判断“以需求码结尾”?

      题目给出了需求码的长度 lenlen 和需求码 codecode。 比如书的编码是 2123,需求码是 23(长度 2)。 要判断 2123 的末尾是不是 23,其实就是看 2123 除以 100100 的余数是不是 23

      数学规律:

      • 取最后 1 位:number % 10
      • 取最后 2 位:number % 100
      • 取最后 kk 位:number % (10的k次方)

      所以,你只需要算出一个模数 mod = 10^len,然后判断 book_id % mod == code 即可。

      2. 策略:如何找到“最小”的?

      题目要求输出最小的那个图书编码。这里有两种处理策略:

      • 策略 A(推荐):先排序,再查找

        • 在读入所有书的编码后,先用 sort 把它们从小到大排序
        • 对于每个读者,从头到尾遍历排好序的书。
        • 找到的第一个符合条件的书,一定就是最小的!直接输出并 break(停止当前读者的查找)。
        • 如果遍历完了还没找到,就输出 -1
      • 策略 B:打擂台

        • 不排序。对于每个读者,遍历所有书。
        • 如果书符合条件,这就更新目前的“最小答案”(ans = min(ans, book_id))。
        • 初始答案设为一个无穷大或者 -1。

      3. 小细节提示

      • 10 的次幂:为了方便,你可以预处理一个数组 p[]p[1]=10, p[2]=100 ...,或者每次用循环算一下模数。尽量避免频繁使用 pow 函数(它是浮点运算,虽说这题也能过,但整数运算更稳)。
      • 输入输出:注意 QQ 是读者的数量,外层循环是 QQ 次。

      代码结构建议

      1. 读入 n, q
      2. 读入 n 本书的编码存入数组 a[]
      3. sort(a + 1, a + n + 1) // 先排好序
      4. 循环 q 次(处理每个读者):
          a. 读入 len, code
          b. 计算模数 mod = 10^len
          c. 遍历数组 a[]:
              如果 (a[i] % mod == code):
                  输出 a[i],标记找到了,break
          d. 如果遍历完没找到,输出 -1
      

      思路很清晰了吧?快去试试写代码吧!

      • 0
        @ 2025-9-10 9:10:22

        C++ :

        #include<bits/stdc++.h>
        using namespace std;
        struct book
        {
            int w;
            int num;
        }a[1000+1];
        int i,j,k,l,n,m,b[1000+1];
        int ask(int x,int a,int y)
        {
            int sz=a;
            int w=1;
            do
        	{
                w*=10;
                sz--;
            }while(sz!=0);
            if((x%=w)==y)return 1;
            else return 0;
        }
        int main()
        {
              cin>>n>>m;
              for(i=1;i<=n;i++){
                  cin>>b[i];
              }
              sort(b+1,b+n+1);
              for(i=1;i<=m;i++)
        	  {
                  cin>>a[i].w>>a[i].num;
              }
              for(i=1;i<=m;i++)
        	  {
                  for(j=1;j<=n;j++)
        		  {
                      k+=ask(b[j],a[i].w,a[i].num);
                      if(ask(b[j],a[i].w,a[i].num)==1)break;
                  }
                  if(k==0)cout<<"-1"<<endl;
                  else cout<<b[j]<<endl;
                  k=0;
              }
              return 0;
        }
        
        • 1

        信息

        ID
        3806
        时间
        1000ms
        内存
        128MiB
        难度
        10
        标签
        递交数
        1
        已通过
        1
        上传者