2022.9.12 第二次vp
场次
部分题解
B
模拟
给定\(A, B, K\),\(A \leq B\),求 \(\frac{A}{B}\) 保留 \(K\) 位小数后的结果,同时需要保证结果满足四舍五入
做法就是每次用 \(A\) 除以 \(B\) ,把整数部分存进答案,然后 \(A\) 乘上 \(10\)
这样做 \(K + 1\) 位后,再从后往前循环处理四舍五入
点击查看代码
// #pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pb push_back
using namespace std;
ll a, b, k;
int main(){
    cin >> a >> b >> k;
	if(a == b) {
		printf("1.");
		for(int i = 1; i <= k ;i++ ) printf("0");
		puts("");
		system("pause");
		return 0;
	}
	
	vector<int>ans;
	while(k >= -1) {
		int x = a / b;
		ans.push_back(x);
		a -= x * b;
		a *= 10;
		k--;
	}
	bool f = 0;
	if(ans.back() >= 5) f = 1;
	for(int i = ans.size()-2; i >= 0; i--) {
		if(f) {
			if(ans[i] <= 9) ans[i]++, f = 0;
			else ans[i] = 0;
		}
	}
	for(int i = 0; i < ans.size() - 1; i++) {
		
		printf("%d", ans[i]); 
		if(i == 0) printf(".");
	}
	puts("");
    system("pause");
    return 0;
}
C
BSGS (baby step, giant step)
已知 \(X_{n+1} =a X_{n}+b \quad (mod\ m)\)
给定 \(a,b,X_0,m,x\), 问 \(x\) 是否能从这个序列中产生
通过推式子可求出 \(a^n\) 的值,然后用 \(BSGS\) 可判断能否求出 \(n\)
细节见代码:
点击查看代码
// #pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pb push_back
using namespace std;
ll a, b, mod, x0, x;
ll X, Y;
ll qpow(ll a,ll b,ll mod){
	ll ans=1;
	while(b){
		if(b%2){
			ans*=a;
			ans%=mod; 
		}
		a*=a;
		a%=mod;  
		b/=2;
	}
	return ans;  
}
ll BSGS(ll a, ll b, ll p) {
	ll cur = 1;
	ll mx = ceil(sqrt(p));  
	map<ll, ll> mp;
	for(int B = 1; B <= mx; B++) {
		cur = cur * a % p;
		mp[b * cur % p] = B;
	}
	ll tem = cur;
	for(int A = 1; A <= mx; A++) {
		if(mp[tem]) return 1ll * A * mx - mp[tem];
		tem = tem * cur % p;
	}
	return -1;
}
int main(){
    cin >> a >> b >> mod >> x0 >> x;
	if(x == x0) {
		puts("YES");
	}
	else if(a == 1) {
		if(b == 0) puts("NO");
		else {
			puts("YES");
		}
	}
	else if(a == 0) {
		if(x == b) puts("YES");
		else puts("NO");
	}
	else {
		ll tem = b * qpow(a - 1, mod - 2, mod);
		ll fz = (x + tem) % mod;
		ll fm = (x0 + tem) % mod;
		ll p = fz * qpow(fm, mod - 2, mod) % mod;
		ll ans = BSGS(a, p, mod);
		if(ans == -1) puts("NO");
		else puts("YES");
	}
    system("pause");
    return 0;
}
I
线段树 + 线性基
有 \(n\) 堆石子, 给你两种操作,选定 \([l,r]\) 区间,第一种是把这个区间的数都加上 \(x\) ,第二种是在这个区间内选一些堆玩 \(Nim \ game\),问后手是否有必胜策略
首先我们知道,后手有必胜策略等同于先手不一定必胜,所以可以看成一般的 \(Nim \ game\) ,就转化成了一些堆的异或和能否为 \(0\) 这一问题
我们使用线性基来解决这个问题。
因为石子的总数最多可能有 \(2*10^9\) ,表示成二进制最多31位,如果堆的数量大于31,那么一定存在一些堆异或起来答案为 \(0\) ,肯定输出 Yes
当堆数小于等于31时,就构造这个区间的线性基,同时判断
点击查看代码
// #pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pb push_back
using namespace std;
const int N = 1e5 + 10;
int n, m;
int a[N];
struct SegTree{
    ll v;
    ll lazy;
}t[N<<2];
void push_up(int rt){
    t[rt].v=t[rt*2].v+t[rt*2+1].v;
}
void push_down(int l,int r,int rt){
    if(t[rt].lazy){
        t[rt*2].lazy+=t[rt].lazy;
        t[rt*2+1].lazy+=t[rt].lazy;
        int mid=(l+r)>>1;
        t[rt*2].v+=t[rt].lazy*(mid-l+1);
        t[rt*2+1].v+=t[rt].lazy*(r-mid);
    }
    t[rt].lazy=0;
}
void build(int l,int r,int rt){
    t[rt].lazy=0;
    if(l==r){
        t[rt].v=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt*2);
    build(mid+1,r,rt*2+1);
    push_up(rt);
}
void upd(int L,int R,int l,int r,int rt,ll v){
    if(l>R||r<L||l>r) return;
    if(L<=l&&r<=R){
        t[rt].lazy+=v;
        t[rt].v+=1ll*v*(r-l+1);
        return;
    }
    push_down(l,r,rt);
    int mid=(l+r)>>1;
    upd(L,R,l,mid,rt*2,v);
    upd(L,R,mid+1,r,rt*2+1,v);
    push_up(rt);
}
ll query(int L,int R,int l,int r,int rt){
    if(L>r||R<l||l>r) return 0;
    if(L<=l&&r<=R){
        return t[rt].v;
    }
    int mid=(l+r)>>1;
    push_down(l,r,rt);   
    return query(L,R,l,mid,rt*2)+query(L,R,mid+1,r,rt*2+1);
}
int main(){
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
	build(1, n, 1);
	for(int i = 1, op, l, r, x; i <= m; i++) {
		scanf("%d%d%d", &op, &l, &r);
		if(op == 2) {
			if(r - l + 1 > 31) {  //[2^0 , 2^30]
				puts("Yes");
				continue;
			}
			else {
				bool flag = 0;
				int b[31] = {0};
				for(int j = l; j <= r; j++) {
					int now = query(j, j, 1, n, 1);
					bool f = 1;
					for(int k = 30; k >= 0; k--) {
						if(now & (1 << k)) {
							if(b[k]) now ^= b[k];
							else {
								b[k] = now;
								f = 0;
								break;
							}
						}
					}
					if(f) flag = 1; 
				}
				if(flag) puts("Yes");
				else puts("No");
			}
		}
		else {
			scanf("%d", &x);
			upd(l, r, 1, n, 1, x);
		}
	}
    system("pause");
    return 0;
}
总结
竟然这场没有我单独过的题,B读错了然后队友喂了题意,帮队友改了一题H,G题wa了学妹给改过了(错得离谱
最近的训练量确实太少了,感觉有一阵没写代码了,写题目很生疏
计划是每两天打一场cf锻炼思维和代码能力
也想要成为别人可以依靠的人啊。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号