• [Codeforces] number theory (R1600) Part.1


    [Codeforces] number theory (R1600) Part.1

    题单:https://codeforces.com/problemset/page/1?tags=number+theory%2C1201-1600

    71C. Round Table Knights

    原题指路:https://codeforces.com/problemset/problem/71/C

    题意 ( 0.5   s ) (0.5\ \mathrm{s}) (0.5 s)

    n n n个人等间距地围成一圈,好人用 1 1 1表示,坏人用 0 0 0表示.问是否存在一个只以好人为顶点的(非退化)正多边形.

    第一行输入一个整数 n    ( 3 ≤ n ≤ 1 e 5 ) n\ \ (3\leq n\leq 1\mathrm{e}5) n  (3n1e5).第二行输入 n n n个整数 0 0 0 1 1 1.

    思路

    枚举间隔的点数 d d d,则有解的必要条件是 d ∣ n d\mid n dn且多边形边数 n d ≥ 3 \dfrac{n}{d}\geq 3 dn3.枚举环上的起点,检查正多边形的顶点是否都是 1 1 1.

    1 e 5 1\mathrm{e}5 1e5内的整数的约数个数最多为 c n t = 128 cnt=128 cnt=128,对每个约数至多需检查常数遍 n n n个顶点,时间复杂度 O ( c n t ⋅ n ) O(cnt\cdot n) O(cntn).

    代码

    void solve() {
    	int n; cin >> n;
    	vi a(n);
    	for (auto& ai : a) cin >> ai;
    
    	for (int d = 1; d <= n; d++) {  // 枚举间隔
    		if (n / d < 3) break;  // 后面的间隔都太大
    		if (n % d) continue;
    
    		for (int begin = 0; begin < d; begin++) {  // 枚举起点
    			bool ok = true;
    			for (int i = begin; i < n; i += d) {  // 检查多边形顶点
    				if (!a[i]) {
    					ok = false;
    					break;
    				}
    			}
    			
    			if (ok) {
    				cout << "YES" << endl;
    				return;
    			}
    		}
    	}
    	cout << "NO" << endl;
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30


    75C. Modified GCD

    原题指路:https://codeforces.com/problemset/problem/75/C

    题意 ( 2   s ) (2\ \mathrm{s}) (2 s)

    给定两正整数 a , b a,b a,b和区间 [ l , r ] [l,r] [l,r],求 a a a b b b在区间 [ l , r ] [l,r] [l,r]内的 gcd ⁡ \gcd gcd,若无解则输出 − 1 -1 1.

    第一行输入两个整数 a , b    ( 1 ≤ a , b ≤ 1 e 9 ) a,b\ \ (1\leq a,b\leq 1\mathrm{e}9) a,b  (1a,b1e9).第二行输入一个整数 t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4),表示询问次数.接下来 t t t行每行输入两个整数 l , r    ( 1 ≤ l ≤ r ≤ 1 e 9 ) l,r\ \ (1\leq l\leq r\leq 1\mathrm{e}9) l,r  (1lr1e9).

    思路

    预处理出 a a a b b b各自的因数,两集合求交即公约数,二分是否存在 [ l , r ] [l,r] [l,r]内的约数即可.

    代码

    vii factors;
    
    void get_factors(int n) {
    	for (int i = 2, d  = 1; (ll)i * i <= n; i += d, d = 2) {
    		if (n % i == 0) {
    			factors.push_back({ i,0 });
    			while (n % i == 0) {
    				n /= i;
    				factors.back().second++;
    			}
    		}
    	}
    	if (n > 1) factors.push_back({ n,1 });
    }
    
    vi divisors;
    
    void get_divisors(int idx = 0, int product = 1) {
    	if (idx == factors.size()) {
    		divisors.push_back(product);
    		return;
    	}
    
    	for (int i = 0; i <= factors[idx].second; i++) {
    		get_divisors(idx + 1, product);
    		product *= factors[idx].first;
    	}
    }
    
    void solve() {
    	int a, b; cin >> a >> b;
    
    	get_factors(a);
    	get_divisors();
    	vi d1 = divisors;  // a的约数
    	
    	factors.clear();
    	divisors.clear();
    	get_factors(b);
    	get_divisors();
    	vi d2 = divisors;  // b的约数
    
    	sort(all(d1)), sort(all(d2));
    	vi common;  // a与b的公约数
    	set_intersection(all(d1), all(d2), inserter(common, common.begin()));
    
    	CaseT{
    		int l, r; cin >> l >> r;
    		
    		int pos = upper_bound(all(common), r) - common.begin() - 1;
    		cout << (pos < 0 || common[pos] < l ? -1 : common[pos]) << endl;
    	}
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57


    123A. Prime Permutation

    原题指路:https://codeforces.com/problemset/problem/123/A

    题意

    给定一个长度为 ∣ s ∣ |s| s的、只包含小写英文字母的字符串 s s s,下标从 1 1 1开始.问是否能重排 s s s中字符的顺序使得对任意素数 p ≤ ∣ s ∣ p\leq |s| ps和任意整数 i ∈ [ 1 , ∣ s ∣ p ] i\in\left[1,\dfrac{|s|}{p}\right] i[1,ps],有 s p = s p ⋅ i s_p=s_{p\cdot i} sp=spi,若能,输出"YES"并输出任一方案;否则输出"NO".

    思路

    显然 s s s中除下标 1 1 1和下标为 > ∣ s ∣ 2 >\dfrac{|s|}{2} >2s的素数外的下标的字符应相同,它们都与下标 2 2 2的字符相同.

    [] 对下标 p o s > ∣ s ∣ 2 pos>\dfrac{|s|}{2} pos>2s的位置,

    ①若 p o s pos pos非素数,则存在一个 ≤ ∣ s ∣ 2 \leq\dfrac{|s|}{2} 2s的素数 p   s . t .   p ∣ p o s p\ s.t.\ p\mid pos p s.t. ppos,进而下标 p o s pos pos的字符与下标 2 2 2的字符相同.

    ②若 p o s pos pos是素数,则该位置的字符可任意.

    最优策略:将 s s s中出现次数最多的字符作为 s s s中除下标 1 1 1和下标为 > ∣ s ∣ 2 >\dfrac{|s|}{2} >2s的素数外的下标的字符.

    代码

    const int MAXN = 1005, MAXM = 30;
    int n;
    char str[MAXN];
    int cnt[MAXM];
    bool same[MAXN];  // 记录字符是否应相同
    
    void solve() {
    	cin >> str + 1;
    
    	n = strlen(str + 1);
    	for (int i = 1; i <= n; i++) cnt[str[i] - 'a']++;
    
    	int idx = 0;  // 出现次数最多的字符的下标
    	for (int i = 0; i < 26; i++)
    		if (cnt[i] > cnt[idx]) idx = i;
    
    	// 预处理出需要相同的字符的下标
    	for (int i = 2; i * i <= n; i++) {
    		if (!same[i])
    			for (int j = i * i; j <= n; j += i) same[j] = true;
    	}
    	for (int i = 2; 2 * i <= n; i++) same[i] = true;
    
    	for (int i = 1; i <= n; i++) {  // 需要相同的字符的位置放出现次数最多的字符
    		if (same[i]) {
    			if (!cnt[idx]) {
    				cout << "NO";
    				return;
    			}
    
    			str[i] = idx + 'a';
    			cnt[idx]--;
    		}
    	}
    	
    	idx = 0;  // 清空
    	for (int i = 1; i <= n; i++) {  // 放剩下的位置
    		if (!same[i]) {
    			while (!cnt[idx]) idx++;
    
    			str[i] = idx + 'a';
    			cnt[idx]--;
    		}
    	}
    
    	cout << "YES" << endl << str + 1;
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51


    150A. Win or Freeze

    原题指路:https://codeforces.com/problemset/problem/150/A

    题意 ( 2   s ) (2\ \mathrm{s}) (2 s)

    A和B两人玩游戏,A先手.初始时纸上有一个整数 n n n,每轮每人写出一个上一个写的数的非平凡因子(非 1 1 1和它本身的因子),不能操作者胜.给定 n    ( 1 ≤ n ≤ 1 e 13 ) n\ \ (1\leq n\leq 1\mathrm{e}13) n  (1n1e13),问最后谁胜利.若A胜,第一行输出 1 1 1,第二行输出他的第一步操作,若他无法进行第一次操作,输出 0 0 0;若B胜,输出 2 2 2.

    思路

    只有当 n n n形如 p q pq pq p 2 p^2 p2时B胜,其中 p , q p,q p,q为素因子.

    对其余情况,先预处理出 n n n的素因子后,若素因子个数为 1 1 1(含重复的素因子),则 n n n为素数,进而A无法进行第一次操作,输出 1 1 1;否则A至少有两个素因子,输出前两个素因子之积即可.

    代码

    void solve() {
    	ll n; cin >> n;
        
      if (n == 1) {
        cout << 1 << endl << 0;
        return;
      }
    
      vl divisors;
      for (ll i = 2; i <= sqrt(n); i++) {
        if (n % i == 0) {
          while (n % i == 0) {
            n /= i;
            divisors.push_back(i);
          }
        }
      }
      if(n > 1) divisors.push_back(n);
    
      if (divisors.size() == 2) cout << 2;
      else {
        cout << 1 << endl;
        cout << (divisors.size() == 1 ? 0 : divisors[0] * divisors[1]);
      }
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29


    154B. Colliders

    原题指路:https://codeforces.com/problemset/problem/154/B

    题意 ( 2   s ) (2\ \mathrm{s}) (2 s)

    有编号 1 ∼ n 1\sim n 1n n n n个机器,要求正在工作的机器的编号两两互素.

    现有两种操作:

    (1) +   i +\ i + i,表示开启 i i i号机器.

    ​ ①若成功开启,则输出"Success".

    ​ ②若 i i i号机器已开启,则输出"Already on".

    ​ ③若开启 i i i机器后,存在 j j j号机器使得 gcd ⁡ ( i , j ) ≠ 1 \gcd(i,j)\neq 1 gcd(i,j)=1,则输出"Conflict with j",此时不开启 i i i号机器.

    (2) −   i -\ i  i,表示关闭 i i i号机器.

    ​ ①若成功关闭,则输出"Success".

    ​ ②若 i i i号机器已关闭,则输出"Already off".

    第一行输入两个整数 n , m    ( 1 ≤ n , m ≤ 1 e 5 ) n,m\ \ (1\leq n,m\leq 1\mathrm{e}5) n,m  (1n,m1e5),分别表示机器数和操作数.接下来 m m m每行输入一个操作,格式如上,数据保证操作合法.

    思路

    预处理出 [ 1 , n ] [1,n] [1,n]中每个数的素因数后,用set模拟上述过程即可.

    代码

    const int MAXN = 1e5 + 5;
    vi divisors[MAXN];  // divisors[i]表示i的素因子
    bool on[MAXN];  // 记录每个机器是否开启
    set s[MAXN];  // s[i]记录当前开启的i的倍数的编号
    
    vi get_divisors(int n) {
    	vi res;
    	for (int i = 2; (ll)i * i <= n; i++) {
    		if (n % i == 0) {
    			res.push_back(i);
    			while (n % i == 0) n /= i;
    		}
    	}
    	if (n > 1) res.push_back(n);
    	return res;
    }
    
    void solve() {
    	int n; cin >> n;
    
    	for (int i = 1; i <= n; i++)  // 预处理出[1,n]中所有数的素因子
    		divisors[i] = get_divisors(i);
    
    	CaseT{
    		char op; int x; cin >> op >> x;
    		if (op == '+') {
    			if (on[x]) {
    				cout << "Already on" << endl;
    				continue;
    			}
    
    			int conflict = 0;  // 冲突的机器编号,0表示无冲突
    			for (auto i : divisors[x]) {
    				if (s[i].size()) {
    					conflict = *s[i].begin();
    					break;
    				}
    			}
    
    			if (conflict) cout << "Conflict with " << conflict << endl;
    			else {
    				cout << "Success" << endl;
    				on[x] = true;
    				for (auto i : divisors[x]) s[i].insert(x);
    			}
    		}
    		else {
    			if (!on[x]) cout << "Already off" << endl;
    			else {
    				cout << "Success" << endl;
    				on[x] = false;
    				for (auto i : divisors[x]) s[i].erase(x);
    			}
    		}
    	}
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60


    158D. Ice Sculptures

    原题指路:https://codeforces.com/problemset/problem/158/D

    题意 ( 3   s ) (3\ \mathrm{s}) (3 s)

    顺时针编号 1 ∼ n 1\sim n 1n n n n个冰雕等间距地围成一圈,其中 i i i号冰雕的好看程度为 a i a_i ai.现要融化若干个(可能为零个)冰雕,使得剩下的冰雕构成一个(非退化的)正多边形,且好看程度之和最大,求好看程度之和的最大值.

    第一行输入一个整数 n    ( 3 ≤ n ≤ 2 e 4 ) n\ \ (3\leq n\leq 2\mathrm{e}4) n  (3n2e4).第二行输入 n n n个整数 a 1 , ⋯   , a n    ( − 1000 ≤ a i ≤ 1000 ) a_1,\cdots,a_n\ \ (-1000\leq a_i\leq 1000) a1,,an  (1000ai1000).

    思路

    显然相邻两保留的冰雕间的距离为 n n n的约数.枚举 n n n的约数 d d d,对每个 d d d,枚举起点 b e g i n begin begin,统计并更新答案即可.

    代码

    void solve() {
    	int n; cin >> n;
      vi a(n);
      for (int& ai : a) cin >> ai;
    
      int ans = -INF;
      for (int d = 1; d <= n; d++) {  // 枚举间隔
        if (n / d < 3) break;  // 后面间隔都太大
        if (n % d) continue;
    
        for (int begin = 0; begin < d; begin++) {  // 枚举起点
          int res = 0;
          for (int i = begin; i < n; i += d) res += a[i];
          ans = max(ans, res);
        }
      }
      cout << ans;
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22


    171F. ucyhf

    原题指路:https://codeforces.com/problemset/problem/171/F

    题意 ( 2   s ) (2\ \mathrm{s}) (2 s)

    称一个素数是emirp的,如果它翻转后是与其本身不同的素数.求第 n    ( 1 ≤ n ≤ 11184 ) n\ \ (1\leq n\leq 11184) n  (1n11184)个emirp的素数,下标从 1 1 1开始.

    思路

    暴力枚举即可.

    11184 11184 11184个emirp的素数是 999983 999983 999983,故答案不会爆int.

    代码

    int get_rev(int n) {
    	string s = to_string(n);
    	reverse(all(s));
    	return stoi(s);
    }
    
    bool is_prime(int n) {
    	if (n <= 2) return n == 2;
    	
    	for (int i = 2; (ll)i * i <= n; i++)
    		if (n % i == 0) return false;
    	return true;
    }
    
    void solve() {
    	int n; cin >> n;
    
    	int ans = 12;  // 从第一个emirp13减1开始
    	while (n) {
    		ans++;
    		if (ans != get_rev(ans) && is_prime(ans) && is_prime(get_rev(ans))) n--;
    	}
    	cout << ans;
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28


    172D. Calendar Reform

    原题指路:https://codeforces.com/problemset/problem/172/D

    题意 ( 2   s ) (2\ \mathrm{s}) (2 s)

    给定正整数 a , n    ( 1 ≤ a , n ≤ 1 e 7 , a + n − 1 ≤ 1 e 7 ) a,n\ \ (1\leq a,n\leq 1\mathrm{e}7,a+n-1\leq 1\mathrm{e}7) a,n  (1a,n1e7,a+n11e7),问 a , a + 1 , ⋯   , a + n − 1 a,a+1,\cdots,a+n-1 a,a+1,,a+n1 n n n个数能拆成多少个正的完全平方数之和.

    思路

    设能整除数 j j j的最大完全平方数为 i 2 i^2 i2.先用筛法预处理出 1 e 7 1\mathrm{e}7 1e7内的 r e s [ j ] = j i 2 res[j]=\dfrac{j}{i^2} res[j]=i2j,再对给定的范围统计答案即可.

    代码

    const int MAXN = 1e7 + 5;
    int res[MAXN];
    
    void init() {
      for (int i = 1; (ll)i * i < MAXN; i++) {
        for (int j = i * i; j < MAXN; j += i * i)
          res[j] = j / (i * i);
      }
    }
    
    void solve() {
      init();
    
    	int a, n; cin >> a >> n;
    
      ll ans = 0;
      for (int i = a; i <= a + n - 1; i++) ans += res[i];
      cout << ans;
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23


    255B. Well-known Numbers

    原题指路:https://codeforces.com/problemset/problem/225/B

    题意 ( 2   s ) (2\ \mathrm{s}) (2 s)

    定义 k k k-bonacci数如下:① F ( k , n ) = 0    ( 1 ≤ n ≤ k ) F(k,n)=0\ \ (1\leq n\leq k) F(k,n)=0  (1nk);② F ( k , k ) = 1 F(k,k)=1 F(k,k)=1;③ F ( k , n ) = F ( k , n − 1 ) + F ( k , n − 2 ) + ⋯ + F ( k , n − k )    ( n > k ) F(k,n)=F(k,n-1)+F(k,n-2)+\cdots+F(k,n-k)\ \ (n>k) F(k,n)=F(k,n1)+F(k,n2)++F(k,nk)  (n>k),其中 n , k ∈ Z n,k\in\mathbb{Z} n,kZ.给定一个正整数 s s s,将其分解为若干个(至少两个)相异的 k k k-bonacci数之和.

    第一行输入两个整数 s , k    ( 1 ≤ s , k ≤ 1 e 9 , k > 1 ) s,k\ \ (1\leq s,k\leq 1\mathrm{e}9,k>1) s,k  (1s,k1e9,k>1).

    第一行输出分解成的 k − k- kbonacci数的个数,第二行输出分解.若有多组解,输出任一组.

    思路

    F ( k , n ) = F ( k , n − 1 ) + F ( k , n − 2 ) + ⋯ + F ( k , n − k )    ( n > k ) F(k,n)=F(k,n-1)+F(k,n-2)+\cdots+F(k,n-k)\ \ (n>k) F(k,n)=F(k,n1)+F(k,n2)++F(k,nk)  (n>k),

    F ( k , n − 1 ) = F ( k , n − 2 ) + F ( k , n − 3 ) + ⋯ + F ( k , n − k − 1 ) F(k,n-1)=F(k,n-2)+F(k,n-3)+\cdots+F(k,n-k-1) F(k,n1)=F(k,n2)+F(k,n3)++F(k,nk1)

    ​ 两式相减得 F ( k , n ) + F ( k , n − k − 1 ) = 2 F ( k , n − 1 ) F(k,n)+F(k,n-k-1)=2F(k,n-1) F(k,n)+F(k,nk1)=2F(k,n1).

    移项得 2 F ( k , n − 1 ) ≥ F ( k , n )    ( n > k ) 2F(k,n-1)\geq F(k,n)\ \ (n>k) 2F(k,n1)F(k,n)  (n>k).显然该不等式当 n ≤ k n\leq k nk时也成立.

    贪心,将 s s s减去能减去的最大的 k − k- kbonacci数直至 s = 0 s=0 s=0.

    [] 只需证明分解中不会出现两个相等的数.若不然,设分解中存在两相等的数 F ( k , x ) F(k,x) F(k,x).

    注意到 2 F ( k , x ) ≥ F ( k , x + 1 ) 2F(k,x)\geq F(k,x+1) 2F(k,x)F(k,x+1),则可将两相等的数替换为 F ( k , x + 1 ) F(k,x+1) F(k,x+1).

    预处理出不超过 s s s的相异的 k − k- kbonacci数,其中求和的部分可类似于滑动窗口.

    代码

    ll s, k; 
    umap kbon;
    vl res;  // 存不同的k-bonacci数
    
    ll cal(int n) {  // 求kbon[n]
      if (n < k) return kbon[n] = 0;
      if (n == k) return kbon[n] = 1;
      return kbon[n];
    }
    
    void init() {  // 预处理出不超过s的k-bonacci数
      res.push_back(0), res.push_back(1);
    
      ll cur = 1;
      int idx = k + 1;
      kbon[idx] = cur;
    
      while (cur <= s) {
        cur -= cal(idx - k), cur += cal(idx);
        kbon[++idx] = cur;
        if (res.back() != cur) res.push_back(cur);
      }
    }
    
    void solve() {
    	cin >> s >> k;
    
      init();
    
      vi ans;
      while (res.size()) {
        if (res.back() <= s) {
          ans.push_back(res.back());
          s -= res.back();
        }
        res.pop_back();
      }
      cout << ans.size() << endl;
      for (auto i : ans) cout << i << ' ';
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44


    230B. T-primes

    原题指路:https://codeforces.com/problemset/problem/230/B

    题意 ( 2   s ) (2\ \mathrm{s}) (2 s)

    称一个正整数是T-prime的,如果它有且只有三个相异的约数.

    t    ( 1 ≤ t ≤ 1 e 5 ) t\ \ (1\leq t\leq 1\mathrm{e}5) t  (1t1e5)组测试数据.每组测试数据输入一个整数 x    ( 1 ≤ x ≤ 1 e 12 ) x\ \ (1\leq x\leq 1\mathrm{e}12) x  (1x1e12).

    对每组测试数据,若 x x x是T-prime的,输出"YES";否则输出"NO".

    思路

    显然只有素数的平方是T-prime的.预处理出 1 e 6 1\mathrm{e}6 1e6内的素数,将它们的平方加入set中即可.

    代码

    const int MAXN = 1e6 + 5;
    int primes[MAXN], cnt;
    bool state[MAXN];
    set s;
    
    void init() {
      for (int i = 2; i < MAXN; i++) {
        if(!state[i]) primes[cnt++] = i;
    
        for (int j = 0; (ll)primes[j] * i < MAXN; j++) {
          state[primes[j] * i] = true;
          if (i % primes[j] == 0) break;
        }
      }
    
      for (int i = 0; i < cnt; i++) s.insert((ll)primes[i] * primes[i]);
    }
    
    void solve() {
      init();
    
      CaseT{
        ll n; cin >> n;
        if(s.count(n)) cout << "YES" << endl;
        else cout << "NO" << endl;
      }
    }
    
    int main() {
    	solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31


  • 相关阅读:
    在服务器上部署 Nginx 并设置图片服务器
    Verilog刷题[hdlbits] :Always if2
    不断迭代的收银系统,工厂_策略_装饰器_反射
    E: Unable to locate package libboost-all-dev
    Spring Cloud Alibaba入门篇
    一个简单的HTML篮球网页【学生网页设计作业源码】
    数据采集的基本方法?
    oracle标准版不支持tts
    Springboot 使用【过滤器】实现在请求到达 Controller 之前修改请求体参数和在结果返回之前修改响应体
    【MATLAB教程案例44】通过matlab学习三维曲面的建模,颜色,透明度,动态变化等——以海浪曲面函数为例
  • 原文地址:https://blog.csdn.net/Hytidel/article/details/126900605