zoukankan      html  css  js  c++  java
  • 异常的校省选赛第三场题解

    正常来讲,校省选赛第三场应该是昨天进行的,但是昨晚CF跪了,导致比赛取消了。

    无法JUDGE,我交了四题ABCD,各题只交了一次,之后就算了,四题加起来就做了四十分钟多那样,感觉很水。

    今天REJUDGE一下,过了AC两题,B题WA了,D题TLE,一看B题代码,马上发现错误了,改了一下,没问题AC。D题就比较纠结,改了好多次,TLE很多次最后优化到过了。

    回归

        A - Little Elephant and Function

                    Time Limit:2000MS    Memory Limit:262144KB    64bit IO Format:%I64d & %I64u

    Description

    The Little Elephant enjoys recursive functions.

    This time he enjoys the sorting function. Let a is a permutation of an integers from 1 to n, inclusive, and ai denotes the i-th element of the permutation. The Little Elephant's recursive function f(x), that sorts the first x permutation's elements, works as follows:

    • If x = 1, exit the function.
    • Otherwise, call f(x - 1), and then make swap(ax - 1, ax) (swap the x-th and (x - 1)-th elements of a).

    The Little Elephant's teacher believes that this function does not work correctly. But that-be do not get an F, the Little Elephant wants to show the performance of its function. Help him, find a permutation of numbers from 1 to n, such that after performing the Little Elephant's function (that is call f(n)), the permutation will be sorted in ascending order.

    Input

    A single line contains integer n (1 ≤ n ≤ 1000) — the size of permutation.

    Output

    In a single line print n distinct integers from 1 to n — the required permutation. Numbers in a line should be separated by spaces.

    It is guaranteed that the answer exists.

    Sample Input

    Input
    1
    
    Output
    1 
    Input
    2
    
    Output
    2 1 
    题目的意思呢,就是写出一个序列,让他的函数可以排出升序……

    水题,马上交了。

    先输出n,再输出1到n-1即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int main(){
    
         int n;
         while(cin>>n){
    
           cout<<n;
           for(int i=1;i<n;i++)
             cout<<" "<<i;
             cout<<endl;
         }
    
    
        return 0;
    
    }

    B题:

    B - Little Elephant and Numbers
    Time Limit:2000MS    Memory Limit:262144KB    64bit IO Format:%I64d & %I64u

    Description

    The Little Elephant loves numbers.

    He has a positive integer x. The Little Elephant wants to find the number of positive integers d, such that d is the divisor of x, and x and d have at least one common (the same) digit in their decimal representations.

    Help the Little Elephant to find the described number.

    Input

    A single line contains a single integer x (1 ≤ x ≤ 109).

    Output

    In a single line print an integer — the answer to the problem.

    Sample Input

    Input
    1
    
    Output
    1
    
    Input
    10
    
    Output
    2
    题目意思是,给定一个x,求k的个数,k为x的约数,且k与x的十进制位至少有一个相同。

    还是水题,暴力搜索,i从1到sqrt(n)搜索,如果i是约数,则判断i与n/i是否与n有相同位,不过我把他们用set存起来再比较,避免n=100,i=10的这种情况的重复计算……

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<set>
    using namespace std;
    int flagA[11]; //寄存0-9中哪一些出现A中
    void init(int A){
         memset(flagA,0,sizeof(flagA));
         int tmpA;
        while(A){
    
         tmpA=A%10;
    
         flagA[tmpA]++;
         A/=10;
       }
    
    }
    bool isSame(int B){
    
       int tmpB;
    
    
       while(B){
         tmpB=B%10;
         if(flagA[tmpB]>0) return true; //把B的每一位提取出来判断是否存在于A中
         B/=10;
    
    
       }
    
       return false;
    
    
    }
    int main(){
    
    
         int n;
    
         set<int> st; //存储所有的约数……感觉可以优化,但是懒得想了
         while(cin>>n){
            st.clear();
            init(n); //一定不要忘记初始化flagA
            double sqrtn=sqrt(n);  
            int cnt=0;
            for(int i=1;i<=sqrtn;i++){
               if(n%i==0){
                   st.insert(i); 
                   st.insert(n/i);
    
               }
    
            }
            set<int>::iterator itr=st.begin();
            while(itr!=st.end()){
              if(isSame(*itr))
                 cnt++;
                 itr++;
            }
    
            cout<<cnt<<endl;
    
    
         }
    
        return 0;
    
    }
    C题:

    C - Little Elephant and Problem
    Time Limit:2000MS    Memory Limit:262144KB    64bit IO Format:%I64d & %I64u

    Description

    The Little Elephant has got a problem — somebody has been touching his sorted by non-decreasing array a of length n and possibly swapped some elements of the array.

    The Little Elephant doesn't want to call the police until he understands if he could have accidentally changed the array himself. He thinks that he could have accidentally changed array a, only if array a can be sorted in no more than one operation of swapping elements (not necessarily adjacent). That is, the Little Elephant could have accidentally swapped some two elements.

    Help the Little Elephant, determine if he could have accidentally changed the array a, sorted by non-decreasing, himself.

    Input

    The first line contains a single integer n (2 ≤ n ≤ 105) — the size of array a. The next line contains n positive integers, separated by single spaces and not exceeding 109, — array a.

    Note that the elements of the array are not necessarily distinct numbers.

    Output

    In a single line print "YES" (without the quotes) if the Little Elephant could have accidentally changed the array himself, and "NO" (without the quotes) otherwise.

    Sample Input

    Input
    2
    1 2
    
    Output
    YES
    
    Input
    3
    3 2 1
    
    Output
    YES
    
    Input
    4
    4 3 2 1
    
    Output
    NO
    

    Hint

    In the first sample the array has already been sorted, so to sort it, we need 0 swap operations, that is not more than 1. Thus, the answer is "YES".

    In the second sample we can sort the array if we swap elements 1 and 3, so we need 1 swap operation to sort the array. Thus, the answer is "YES".

    In the third sample we can't sort the array in more than one swap operation, so the answer is "NO".

    还是水题!!!!

    都是水题啊!!所以我才能刷得那么快!

    题目的意思是:

    这个大笨象有一个序列,他能不能之多交换其中一对元素,使得序列弱递增。

    思路:先排序……再看看排序前后不同的个数是不是大于2,如果是的话,无法一次交换,输出“NO”,否则可以,输出“YES”。

    我用的是优先队列。从尾部比较,边比较边POP,如果个数大于2,就BREAK掉并且输出NO。

    #include<iostream>
    #include<queue>
    #include<vector>
    using namespace std;
    int main(){
       int n;
       vector<int> v;
       priority_queue<int> pq;
       int i;
       while(cin>>n){
         v.clear();
         v.resize(n);
         while(!pq.empty()){pq.pop();}
         for(i=0;i<n;i++){
           cin>>v[i];
           pq.push(v[i]);
         }
         int cnt=0;
         for(i=n-1;i>=0&&cnt<=2;i--){
           if(v[i]!=pq.top()){
             cnt++;
           };
           pq.pop();
         }
    
         if(cnt<=2) cout<<"YES"<<endl;
         else cout<<"NO"<<endl;
    
       }
    
       return 0;
    }
    D题:

    D - Little Elephant and Array
    Time Limit:4000MS    Memory Limit:262144KB    64bit IO Format:%I64d & %I64u

    Description

    The Little Elephant loves playing with arrays. He has array a, consisting of n positive integers, indexed from 1 to n. Let's denote the number with index i as ai.

    Additionally the Little Elephant has m queries to the array, each query is characterised by a pair of integers lj and rj (1 ≤ lj ≤ rj ≤ n). For each query lj, rj the Little Elephant has to count, how many numbers x exist, such that number x occurs exactly x times among numbers alj, alj + 1, ..., arj.

    Help the Little Elephant to count the answers to all queries.

    Input

    The first line contains two space-separated integers n and m (1 ≤ n, m ≤ 105) — the size of array a and the number of queries to it. The next line contains n space-separated positive integers a1, a2, ..., an (1 ≤ ai ≤ 109). Next m lines contain descriptions of queries, one per line. The j-th of these lines contains the description of the j-th query as two space-separated integers lj and rj (1 ≤ lj ≤ rj ≤ n).

    Output

    In m lines print m integers — the answers to the queries. The j-th line should contain the answer to the j-th query.

    Sample Input

    Input
    7 2
    3 1 2 2 3 3 7
    1 7
    3 4
    
    Output
    3
    1
    这题不算水题啦!但是我还是当成水题来做……因为我喜欢用简单的方法来解题。

    当然,赛后看别人的很多都是用线段树,可是我不懂线段树啊!!!!

    题目的意思是:有n长序列,m此访问,每次访问给定a,b,表示在[a,b]中执行查询,查询的是数字 x恰好出现x次的个数!比如

    7 2

    3 1 2 2 3 3 7

    1 7

    3 4

    就是一个七长的序列,{3,1,2,2,3,3,7},1到 7区间中 1出现了1次,2出现了2次,3出现了3次,这是满足条件的,而7出现只有一次,所以不满足,最后输出的是3次。

    而3到4这个区间,只有2满足(2出现了2次),所以输出是1

    当然,一看题目就知道是区间统计问题啦,懂线段树的大神们应该也会觉得是水题!但是我没有这个“武器”(明天补!),所以之能用普通的思想了。

    ai的范围很大了10^9次方,不过这个完全不用管,因为n才10^5次方,大于10^5次方的ai直接看成0可以了(不可能出现那么多次啊!)

    接下来就是怎么统计的问题了,如果是每次都是线性的话,因为m也有10^5次方,这样下来,10^10次方这个数量级肯定是TLE的(计算机一秒大概就是处理10^8次方这个级别。)

    但是仔细想想,在考虑范围的数也不超过500个。sum(i^2)(1<=i<=500)很容易知道大于10^5次方。我们如果一次统计出在区间中这五百个数的出现情况,那么每个查询只需要500内即可,那么运算就可以降低为500*10^5,明显可以通过的。

    我的做法:

    找出可能满足的数,我的做法是筛选10^5次方一下的ai,并且用一个计数数组p[]来存储个数。之后再遍历n,找出满足p[a[i]]>a[i]并且没有被标号的 a[i],来编号,编号用mp[]来存储,同时用mp2[]来记下逆映射,因为后面我们根据编号来统计!

    之后我用一个dp[100005][500]来记下出现情况, dp[c][d]为[0,c]中d编号的数字出现的次数。

    统计过程就是,从编号一到编号的最大数遍历,对于每一个编号i,统计从区间1到n编号i的出现次数,转移过车功能就是

    if(mp[a[k]]==i) dp[k][i]=dp[k-1][i]+1; //i为编号,k为当前指向区间右侧

    else dp[k][i]=dp[k-1][i];

    查询[x,y]过程就是

    i从1到最大编号

    if( dp[y][i]-dp[x-1][i]==mp2[i])//记得mp2吧,作用就在这里!

    cnt++

    最后输出cnt即可

    代码:

    #include<iostream>
    #include<cstring>
    #include<set>
    #include<map>
    #include<cmath>
    #include<cstdio>
    using namespace std;
    int p[100005];  //p计算次数
    int a[100005];  //a为储存数据与
    int mp[100005];  //mp为从数字到编号,记得数字大于10^5次方是不肯能的,直接化成0
    int mp2[100005]; //mp2是从编号到数字,是mp的逆映射
    int dp[100005][500];  //dp[c][d]为[0,c]中d编号的数字出现的次数.
    
    
    int main(){
    
      int n,m,x,y;//读入变量
      int i,k;//循环变量
    
       scanf("%d%d",&n,&m);
         for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]>100000) a[i]=0;
    
            p[a[i]]++;
         }
         int j=1;  //j表示当前映射到的编号
         for(i=1;i<=n;i++){
             if(p[a[i]]>=a[i]&&mp[a[i]]==0){ //a[i]出现次数>= a[i]且没有被编号
                mp[a[i]]=j; //隐射到编号j
                mp2[j]=a[i];//mp的逆映射
                j++;      
             }
    
         }
         for(i=1;i<j;i++){   //
             
             dp[0][i]=0;
             for(k=1;k<=n;k++){
    
                if(mp[a[k]]==i){
                   dp[k][i]=dp[k-1][i]+1;  //满足加1
                }else{
    
                   dp[k][i]=dp[k-1][i];   
                }
             }
    
         }
    
         while(m--){
            int cnt=0;
    
            scanf("%d%d",&x,&y);
            for(i=1;i<j;i++)
            if(dp[y][i]-dp[x-1][i]==mp2[i]){   //区间计数
               cnt++;
            }
            printf("%d
    ",cnt);
    
    
         }
    
    
    
    
      return 0;
    }




  • 相关阅读:
    atitit.nfc 身份证 银行卡 芯片卡 解决方案 attilax总结
    atitit.php 流行框架 前三甲为:Laravel、Phalcon、Symfony2 attilax 总结
    Atitit.执行cmd 命令行 php
    Atitit. 图像处理jpg图片的压缩 清理垃圾图片 java版本
    atitit。企业组织与软件工程的策略 战略 趋势 原则 attilax 大总结
    atitit. 管理哲学 大毁灭 如何防止企业的自我毁灭
    Atitit.java的浏览器插件技术 Applet japplet attilax总结
    Atitit.jquery 版本新特性attilax总结
    Atitit. 软件开发中的管理哲学一个伟大的事业必然是过程导向为主 过程导向 vs 结果导向
    (转)获取手机的IMEI号
  • 原文地址:https://www.cnblogs.com/dengyaolong/p/3697201.html
Copyright © 2011-2022 走看看