zoukankan      html  css  js  c++  java
  • Codeforces 1470B Strange Definition

    ( ext{不一样的阅读体验})

    (mathcal{Translate})

    注: "(x,y) adjacent" 译作 "(x,y) 相邻"

    定义 (x,y) 相邻需要满足 (frac{lcm(x,y)}{gcd(x,y)}) 是完全平方数。

    共有 (t) 组数据。

    对于每一种数据,给定长度为 (n) 的序列 (a_i),从第 (1)(a) 开始变换,每一次 (a_i) 变成所有与它相邻的数的乘积(包括它自己)。

    定义 (d_i)(a) 中与 (a_i) 相邻的数的个数。

    共有 (q) 次询问,每次询问给出一个 (w),回答第 (w) 秒时(也就是经过 (w) 次变换后)的 (max d_i)

    (mathcal{Solution})

    (frac{lcm(x,y)}{gcd(x,y)}=frac{x imes y}{gcd(x,y)^2})

    (ecause gcd(x,y)^2) 是完全平方数。

    ( herefore frac{x imes y}{gcd(x,y)^2}) 是完全平方数等价于 (x imes y) 是完全平方数。

    (x imes y) 是完全平方数。

    ( herefore x imes y) 质因数分解后每个底数的指数都是偶数。

    ( herefore x,y) 分别质因数分解之后各个底数的指数奇偶性相同。

    到这里显然可以得出相邻是具有传递性的。

    考虑把每个串质因数分解后出的指数模 (2) 看成一个 (01) 串,若 (01) 串相等则这两个数是相邻的。

    若多个数相乘,最后的乘积的 (01) 串为所有因数的 (01) 串的异或后结果(看成每个质因子分别相乘即可说明此点)。

    那么考虑对相同的 (01) 串看成一个集合,考虑一次变换,若 (01) 串为全 (0) 或集合大小为奇数则这些 (01) 串不变,否则这些 (01) 串都变成 (0)

    那么显然只有第一次变换是有用的,这会使所有集合大小为偶数的 (01) 串变成全 (0)

    分别统计第 (0) 秒和第 (1) 秒时的答案即可,后面的答案和第 (1) 秒相同。

    (01) 串为 (1) 的位置拿下来哈希放在一个 (map) 里面就能做了。

    一组数据的时间复杂度为 (mathcal{O}(nlog n+nsqrt{max a_i}))

    (mathcal{Code})

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<map>
    #define pb push_back
    #define pp std::pair<unsigned long long, unsigned long long> 
    #define mp std::make_pair
    #define fir first
    #define sec second
    #define ll long long
    #define re register
    #define ull unsigned long long
    //#define int long long
    inline int Max(int x, int y) { return x > y ? x : y; }
    inline int Min(int x, int y) { return x < y ? x : y; }
    inline int Abs(int x) { return x < 0 ? ~x + 1 : x; }
    inline int read() {
    	int r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-') w = 1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		r = (r << 3) + (r << 1) + (ch ^ 48);
    		ch = getchar();
    	}
    	return w ? ~r + 1 : r;
    }
    //#undef int
    const int N = 300010;
    const ull base = 21841;
    const ull mod = 29050993; 
    const ull base2 = 1429;
    const ull mod2 = 68861641;
    int n, a[N], ans1, ans2;
    pp hs[N];
    std::map<pp, int>vis;
    
    pp hasher(int x) {
    	std::vector<int>vec; int xx = x;
    	for(int i = 2; i * i <= xx; ++i)
    		if(x % i == 0) {
    			int ct = 0;
    			while(x % i == 0) x /= i, ++ct;
    			if(ct&1) vec.pb(i); 
    		}
    	if(x > 1) vec.pb(x);
    	ull sum1 = 0, sum2 = 0;
    	std::sort(vec.begin(), vec.end());
    	int len = vec.size(); 
    	for(int i = 0; i < len; ++i) sum1 = (sum1 * base % mod + (ull)vec[i]) % mod;
    	for(int i = 0; i < len; ++i) sum2 = (sum2 * base2 % mod2 + (ull)vec[i]) % mod2;
    	return mp(sum1, sum2);
    }
    
    void solve() {
    	n = read(); vis.clear(); ans1 = ans2 = 0;
    	for(int i = 1; i <= n; ++i) a[i] = read();
    	for(int i = 1; i <= n; ++i) hs[i] = hasher(a[i]), vis[hs[i]]++, ans1 = Max(ans1, vis[hs[i]]);
    	for(int i = 1; i <= n; ++i) if(vis[hs[i]] % 2 == 0 || hs[i].fir + hs[i].sec == 0) ans2 += vis[hs[i]], vis[hs[i]] = 0;
    	ans2 = Max(ans1, ans2);
    	int q = read();
    	ll x;
    	while(q--) {
    		scanf("%lld", &x);
    		if(x == 0) printf("%d
    ", ans1);
    		else printf("%d
    ", ans2);
    	}
    }
    
    signed main() {
    	int T = read();
    	while(T--) solve(); 
    	return 0;
    }
    
  • 相关阅读:
    Java的简单书写格式
    注解(Annotation)
    Container(容器)与 Injector(注入)
    maven的下载,安装配置以及build一个java web项目
    Version Control,Git的下载与安装
    URL和URI的区别
    HTTP请求解析过程 (简单概括)
    函数式编程语言(functional language)
    HTTP1.1协议中文版-RFC2616
    练习--str
  • 原文地址:https://www.cnblogs.com/do-while-true/p/14242801.html
Copyright © 2011-2022 走看看