3 条题解

  • 1
    @ 2026-4-10 15:07:53

    如果要确定a在序列中出现的次数是否大于等于b,且b出现的次数大于等于a,可以创建一个数组来统计出现数字的次数,然后再对每一个数字的次数进行维护。

    注意到数字a的出现的次数肯定在 [1,cnt[a]] 的范围内,那就可以确定可能的b肯定也在1到cnt[a]的范围内,因此对该区间内的数做一个判断,即判断区间内出现的数字的出现次数是否大于等于a即可。

    #include <bits/stdc++.h>
    #define all(x) (x).begin(), (x).end()
    #define pb push_back
    #define pf push_front
    using namespace std;
    using ll = long long;
    using ull = unsigned long long;
    typedef pair<int, int> P;
    const int mod = 998244353;
    const int MOD = 1e9 + 7;
    
    void solve()
    {
        int n;
        cin >> n;
        vector<int> cnt(n + 1); // 统计读入的数的出现次数
        for (int i = 1; i <= n; i++)
        {
            int ai;
            cin >> ai;
            cnt[ai]++;
        }
        int ans = 0;
        for (int i = 1; i <= n; i++)
        {
            if (!cnt[i])
                continue;
            for (int j = 1; j <= cnt[i]; j++)
            {
                if (cnt[j] >= i) // 判断数字次数是否大于等于a
                    ans++;
            }
        }
        cout << ans << endl;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int T = 1;
        //    cin >> T;
        while (T--)
        {
            solve();
        }
        return 0;
    }
    
    • 0
      @ 2026-4-6 18:00:33

      import java.util.ArrayList; import java.util.Scanner; public class Main {

      public static void main(String[] args) {
          Scanner sc = new Scanner(System.in);
          //思路
          int n=sc.nextInt();
          int ans=0;
          int[]cnt=new int[200001];//计数
          boolean[]vis=new boolean[200001];//判断是否读入,去重
          ArrayList<Integer>list=new ArrayList<>();//存数     
          
          for(int i=0;i<n;i++) {
          	int m=sc.nextInt();
          	cnt[m]++;
      

      //
      if(!list.contains(m))list.add(m);太慢->vis

            if(!vis[m]) {
          		list.add(m);//没读入的话
          		vis[m]=true;
          	}
          }
          
          for(int i=0;i<list.size();i++) {//一个数跟每个数配对      
      

      // for(int j=0;j<list.size();j++) { // int a=list.get(i),b=list.get(j); // if(cnt[a]>=b&&cnt[b]>=a)ans++; // }超时

            int a=list.get(i);//先枚举a
          	for(int b=1;b<=cnt[a];b++) {//再枚举<=cnt[a]的b
          		if(vis[b]&&cnt[b]>=a)ans++;//看是否有数,和满足另一个条件
          	}
          }
          System.out.println(ans);
      }
      

      }

      • 0
        @ 2026-4-2 10:54:41
        #include<bits/stdc++.h>
        using namespace std;
        #define int long long
        /* 完美数队:a,b 如果a出现次数>=b 且b出现次数>=a 既可以
          //思路:一步一步来:暴力到优化  
           次数:想到1排序+map 2去重!!!!!!
          //优化思路:
           1去重 将n转化为sum 已经小很多了
           2 a,b<=sart(n) 即某数>sqrt(n)必然木有完美数对  
        */
        const int N=2e5+5;
        int a[N],cnt[N];
        int un[N];
        int n,ans;
        signed main()
        { std::ios::sync_with_stdio(0);
          cin.tie(0),cout.tie(0);
            cin>>n;
        	for(int i=1;i<=n;i++) 
        	{
        	  cin>>a[i];
        	  cnt[a[i]]++;	
            }
            int sum=0;
        	for(int i=1;i<=sqrt(n);i++)//去重 ---且不过sqrt(n) 
        	{
        	  if(cnt[i]>=1) un[++sum]=i;	
        	}
        	//暴力直接处理:找目表 sort想不出来就不想了
        	for(int i=1;i<=sum;i++)//二重枚举所以情况 这里其实已经优化了 因为sum已经小n很大 
        	 for(int j=1;j<=sum;j++)
        	 {
        	 	if(cnt[un[i]]>=un[j]&&cnt[un[j]]>=un[i])
        	 	 ans++;
             }	
        	cout<<ans<<"\n";
        	return 0;
        }
        • 1

        信息

        ID
        598
        时间
        1000ms
        内存
        256MiB
        难度
        7
        标签
        递交数
        167
        已通过
        43
        上传者