2023.11.5 一点题解

cf 1766D


题目大意:给你两个数x,y
cnt = 0
while (gcd(x, y) == 1) x++, y++, cnt++;
求cnt的结果

gcd性质:gcd(x, y) == gcd(x, y - x)
则gcd(x + k, y + k) == gcd(x + k, y - x) == 1。
枚举y-x的素因子p,找出满足(x + k) % p == 0的k的最小值。
(x + k) % p == 0 ——> k = p - x % p 。

 

const int N = 1e7 + 5;
int mp[N];
vector primes;

void init() {   //求出最小质因子
	for (int i = 2; i <= N; i++) {
        if (!mp[i]) {
            mp[i] = i;
            primes.push_back(i);
        }
        
        for (auto p : primes) {
            if (i * p > N) break;
            mp[i * p] = p;
            if (i % p == 0) break;
        }
    }
}

void solve() {
	int x, y;
	cin >> x >> y;

	if(y - x == 1) {
		cout << -1 << "\n";
		return;
	}

	if(__gcd(x, y) != 1) {
		cout << 0 << "\n";
		return;
	}

	int now = y - x;
	int ans = 1e9;

	while(now > 1) {   
		int tmp = mp[now];
		ans = min(ans, tmp - x % tmp);  //答案取最小值
		now /= tmp;  //质因数分解
	}

	cout << ans << "\n";
} 
cf 1731C

题目大意:给你一个长度为n的数组a(2<=n<=2e5,1<=a[i]<=n),
求有多少个i,j(i<=j)满足a[i]^a[i+1]...^a[j]的因子数为偶数。

从反面出发,求子数组异或和为奇数的个数,用总数减去即使答案。
思考:什么样的数因子数为奇数个? 完全平方数。
异或前缀和,在当前位置判断它前面有多少个数与它异或的值为完全平方数。
做法:枚举2n以内的所有完全平方数(子数组的最大异或和不会超过2n),统计前面出现过的异或前缀和的个数,
用总数减去满足条件的个数。

void solve() {
	int n;
	cin >> n;

	ll ans = 1LL * n * (n + 1) / 2;
	vector cnt(2 * n);
	int cur = 0;
	cnt[cur]++;
	for (int i = 0; i < n; i++) {
		int a;
		cin >> a;
		cur ^= a;
		for (int j = 0; j * j < 2 * n; j++) {
			if((cur ^ (j * j)) < 2 * n) {
				ans -= cnt[cur ^ (j * j)];
			}
		}
		cnt[cur]++;
	}

	cout << ans << "\n";
} 
cf 1895D

题目大意:
给你n-1个整数:a1,a2...a[n-1]。
你的任务是构造一个长度为n的数组b,满足一下条件:
0~n-1都在b中恰好出现一次,a[i] = b[i] ^ b[i + 1](1<=i<=n-1)。

看到异或这种直接算的不好算的东西,首先很自然的就要往拆位,按照每一位考虑方向想一想。
由a[i]=b[i]^b[i+1]简单推导一下:
a[1]=b[1]^b[2]
a[1]^a[2]=b[1]^b[3]
a[1]^a[2]^a[3]=b[1]^b[4]
...
可以看出b[i]=b[1]^(a[i - 1]^...^a[1])
所以我们只需要求出b[1]
求b[1]:先把a数组异或前缀和一下,统计0~n-1与a[1]~a[n-1]之间每一位中1的个数,若不相等则b[1]该位为1。

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
	
	int n;
	cin >> n;

	vector a(n - 1);
	for (int i = 0; i < n - 1; i++) {
		cin >> a[i];
	}    
	for (int i = 1; i < n - 1; i++) {
		a[i] ^= a[i - 1];
	}

	int b1 = 0;
	for (int i = 0; i < 20; i++) {
		int cnt1[2]{}, cnt2[2]{};
		for (int j = 0; j < n; j++) {
			cnt1[j >> i & 1]++;
		} 
		for (int j = 0; j < n - 1; j++) {
			cnt2[a[j] >> i & 1]++;
		}
		if(cnt1[1] != cnt2[1]) {
			b1 |= 1 << i;
		}
	}
	cout << b1 << ' ';
	for (int i = 0; i < n - 1; i++) {
		cout << (a[i] ^ b1) << " \n"[i == n - 2];
	}
 
    return 0;
}

你可能感兴趣的:(算法)