2 条题解

  • 0
    @ 2024-9-7 21:03:06

    筛法

    可以注意到:将 ii 分解因式后得到的因数个数为奇数,那么第 ii 个灯就是亮的,所以我们按着这个思路筛。

    所以借助埃筛的思想,我们记录每次遍历到 jj 的次数,这个次数就是它的因数的个数。

    注意我们要初始化数组的值为 11

    时间复杂度为 O(nlogn)O(n\log n)

    #include <bits/stdc++.h>
    
    using u32 = unsigned;
    using i64 = long long;
    using u64 = unsigned long long;
    using i128 = __int128;
    
    int main() {
    	std::ios::sync_with_stdio(false);
    	std::cin.tie(nullptr);
    
    	int n;
    	std::cin >> n;
    
    	std::vector<int> f(n + 1, 1);
    	for (int i = 2; i <= n; i++) {
    		for (int j = i; j <= n; j += i) {
    			f[j]++;
    		}
    	}
    
    	for (int i = 1; i <= n; i++) {
    		if (f[i] & 1) {
    			std::cout << i << " ";
    		}
    	}
    
    	return 0;
    }
    
    • 0
      @ 2024-9-6 13:48:51

      可以直接模拟开关灯,每次对灯的状态取反即可,但是数据如果大了,就无法成功通过题目。

      对于一盏灯,一开一关为 22 次,所以经过偶数次开关,灯的状态不会变。对任意一个小于 NN 的正整数 xx,只有因数个数为奇数时,才能让灯由关到开。而对于 xx 的任意一个因数i,总存在因数 xi\frac xi 。若 ixii \neq \frac xi,那么 xx 的因数个数就为偶数;相反,若 i=xii = \frac xi时,即 x=i2x = i^2xx 的因数个数就为奇数,此时,xx 就是一个完全平方数。所以只需从 11NN 枚举完全平方数就可以了。

      #include <bits/stdc++.h>
      
      int main()
      {
      	int n;
      	std::cin >> n;
      	for (int i = 1; i*i <= n; i ++) {
      		std::cout << i * i << ' ';
      	}
      	return 0;
      }
      
      • 1

      信息

      ID
      97
      时间
      1000ms
      内存
      256MiB
      难度
      5
      标签
      递交数
      37
      已通过
      16
      上传者