2024.3.8 学习日志(周赛游记)

下午周赛。

想抢T2首A结果虽然一眼秒了,但打慢了点,只拿到了second AC  /kk。

然后先开了T3,开始不是很会,手玩了会样例,感觉是推式子,应该是推对了,但是写完挂成50分了,赛时没调出来。 赛后发现没考虑 26 ^ n % p 为 1 的情况,输麻了。

之后开了T1也是一眼瞄,只不过码的没T2快。

之后在后4题兜兜转转,能拿的分都尝试了一会,最终后四题只拿了30分,遗憾。

晚上订题。

T1, 将 a1 分解质因数,对于每个 gcd(a1, ai) 尝试除a1的每个质因数,找到能初的最小的质因数就好了,特判下 gcd 为 1 的情况。

code: 

#include<bits/stdc++.h>
#define int long long
#define debug puts("原始人,启洞!");
using namespace std;
const int N = 1e5 + 10;
int a[N];
int pri[N], tot;
signed main() {
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	int n;
	scanf("%lld", &n);
	for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	int x = a[1];
	for(int i = 2; i * i <= x; i++){
		if(x % i == 0){
            while(x % i == 0) x /= i;
            pri[++tot] = i;
        }
	}
	for(int i = 1; i <= n; i++){
		int ans = __gcd(a[1], a[i]);
		bool flag = 0;
		for(int j = 1; j <= tot; j++)
			if(ans % pri[j] == 0){
				ans /= pri[j];
				flag = 1;
				// cout << ans;
				break;
			}
		if(flag)
			printf("%lld ", ans);
		else{
			if(ans != 1) printf("1 ");
			else printf("-1 ");
		}
	}
    return 0;
}//by hwl

T2,手玩后发现每个出现的关系都可以互相推出来,所以可以用并查集来维护下每个连通块,退后统计有多少连通块就好了。

code:

#include<bits/stdc++.h>
//#define int long long
#define debug puts("原始人,启洞!");
using namespace std;
const int N = 1e5 + 10;
int fa[N];

int find(int x){
	if(x == fa[x]) return x;
	else return fa[x] = find(fa[x]);
}

void merge(int x, int y){
	x = find(x), y = find(y);
	fa[x] = y;
	return;
}
bool flag[N];

int main() {
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	int n, m;
	cin >> n >> m;
	for(int i = 1; i <= n; i++) fa[i] = i;
	for(int _ = 1; _ <= m; _++){
		int x, y, z;
		cin >> x >> y >> z;
		if(find(x) == find(y)) continue;
		merge(x, y);
	}
	int ans = 0;
	for(int i = 1; i <= n; i++){
		int fa = find(i);
		if(!flag[fa]){
			flag[fa] = 1;
			ans++;
		}
	}
	cout << ans << endl;
    return 0;
}//by hwl

T3,推式子,设长度为n,当前哈希值为x,下一个哈希值为y,要求的字符代表制为a,则具体式子就是解:

26  *(x -  a * 26 ^ (n - 1))+ a = y

化简后就是:

a =  (26 * x - y) / (26 ^ n - 1)

注意分母为零的情况。

code:

#include<bits/stdc++.h>
#define int long long
#define debug puts("原始人,启洞!");
using namespace std;
const int N = 1e5 + 10;
int a[N], v[N];

int qpow1(int a, int b, int mod){
	int res = 1;
	while(b){
		if(b & 1) res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}	
	return res;
}

int C_inv(int x, int mod){//快速幂——费马小定理求逆元
    return qpow1(x, mod - 2, mod);
}
// vector<int> v;

signed main() {
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	// int op = qpow(26, 5);
	// int ans = (26 * 10 - (op - 1) * 18) % 31;
	// cout << (ans + 31) % 31<< endl;
	// ans *= C_inv(11881375, 31);
	// ans = (op - 1) * 18 % 31;
	// cout << ans << " " << (26 * 10 % 31 - 15 + 31) % 31 << endl;
	// cout << ans / (op - 1) << endl;
	// ans = (26 * 10 % 31 - 15 + 31) % 31 * C_inv(op - 1, 31);
	// cout << (ans + 31) % 31<< endl;
	
	
	
	
	int n, p, op;
	cin >> n >> p;
	op = qpow1(26, n, p);
	if(op == 1){
		for(int i = 1; i <= n; i++) cin >> a[i];
		for(int i = n; i >= 1; i--){
			v[i] = a[1] % 26;
			a[1] /= 26;
		}
		for(int i = 1; i <= n; i++)
			cout << char(v[i] + 'a');
		cout << endl;
		return 0;
	}
	// cout << op << endl;
	int x, y, z;
	cin >> x;
	z = x;
	for(int i = 1; i < n; i++){
		cin >> y;
		int ans = ((26 * x % p - y) % p + p) % p;
		ans = (ans % p * (C_inv(op - 1, p) % p + p) % p) % p;
		cout << char(ans + 'a');
		x = y;
	}
	y = z;
	int ans = ((26 * x % p - y) % p + p) % p;
	ans = (ans % p * (C_inv(op - 1, p) % p + p) % p) % p;
	cout << char(ans + 'a');
	cout << endl;
    return 0;
}//by hwl

T4,dp题(由于作者太懒了,打算鸽一会题解 (doge   )

2024.3.15 补充:

因为操作方案相同我们构造出来的数列可能会不同。

于是我们想到一种方法。

枚举最开始哪一位的数。

然后dp。

但是这样会T。

那么我们的时间瓶颈在哪呢?

就是我们枚举最开始的那一位导致的。

那么我们可以强制规定末尾为零。

每次加a,减b,可以用差分的思想,将整个数列减去一个数,就保证了末尾为0啦。

code:

#include <bits/stdc++.h>
// #define int long long
using namespace std;
const int N = 1e3 + 10, mod = 100000007;
int f[N][N];
signed main(){
    //freopen(".in", "r", stdin);
    //freopen(".out", "w", stdout);
    int n, s, a, b;
    cin >> n >> s >> a >> b;
    f[0][0] = 1;
    for(int i = 1; i < n; i++){
    	for(int j = 0; j < n; j++)
    		f[i][j] = (f[i - 1][((j - i * a) % n + n) % n] + f[i - 1][((j + i * b) % n + n) % n]) % mod;
    }
    cout << f[n - 1][(s % n + n) % n] % mod << endl;
    return 0;
}//by hwl

T6:

模拟即可。(当然是假的)

分类讨论。

知道有红太狼的话,一次全部出掉肯定不劣。

所以显出红太狼。

然后知道有美羊羊的话,那么出了美羊羊就一定会有胜负。

所以必须自己能赢的时候才出美羊羊。

大致就是这样,具体可以理解代码。

code:

#include<bits/stdc++.h>
//#define int long long
#define debug puts("原始人,启洞!");
#define win1 puts("Meiyangyang");
#define win2 puts("Xiyangyang");
#define Draw puts("Draw");
using namespace std;
const int N = 10;

struct Hwl{
	int hui, xi, hong, mei;
}a, b;

int main() {
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	int T;
	cin >> T;
	while(T--){
		cin >> a.hui >> a.xi >> a.hong >> a.mei;
		cin >> b.hui >> b.xi >> b.hong >> b.mei;
		
		if(a.hong != 0){
			if(b.hui - a.hong < 0){
				win1;
				continue;
			}else b.hui -= a.hong;
			a.hong = 0;
		}
		
		if(a.mei != 0){
			if(a.hui >= b.hui){
				win1;
				continue;
			}
		}
		
		if(b.xi == 0 && a.hui != 0){
			win1;
			continue;
		}
	
		if(b.hong != 0){
			if(a.hui - b.hong < 0){
				win2;
				continue;
			}else a.hui -= b.hong;
			b.hong = 0;
		}
		
		if(b.mei != 0){
			if(b.hui >= a.hui){
				win2;
				continue;
			}
		}
		
		if(a.xi == 0 && b.hui != 0){
			win2;
			continue;
		}
		
		// if(a.mei == 0 && b.mei == 0){	//b.mei == 0 a.mei == 0
			// int x = 0x3f3f3f3f, y = 0x3f3f3f3f;
			// if(a.hui > b.xi) x = b.xi + 1;
			// if(b.hui > a.xi) y = a.xi + 1;
			// if(x == 0x3f3f3f3f && y == 0x3f3f3f3f){
				// Draw;
				// continue;
			// }
			// if(x <= y){
				// win1;
				// continue;
			// }else{
				// win2;
				// continue;
			// }
		// }
// 		
		// if(a.mei == 0 && b.mei == 1){	//a.mei == 0 b.mei == 1
			// int x = 0x3f3f3f3f, y = 0x3f3f3f3f;
			// if(a.hui > b.xi) x = b.xi + 1;
			// if(b.hui > a.xi) y = a.xi + 1;
			// if(a.hui - b.hui + 1 >= b.xi) y = min(y, a.hui - b.hui + 1);
			// if(x == 0x3f3f3f3f && y == 0x3f3f3f3f){
				// Draw;
				// continue;
			// }
			// if(x <= y){
				// win1;
				// continue;
			// }else{
				// win2;
				// continue;
			// }
		// }
// 		
		// if(a.mei == 1 && b.mei == 0){	//a.mei == 1 b.mei == 0
			// int x = 0x3f3f3f3f, y = 0x3f3f3f3f;
			// if(a.hui > b.xi) x = b.xi + 1;
			// if(b.hui > a.xi) y = a.xi + 1;
			// if(b.hui - a.hui + 1 >= a.xi) x = min(x, b.hui - a.hui + 1);
			// if(x == 0x3f3f3f3f && y == 0x3f3f3f3f){
				// Draw;
				// continue;
			// }
			// if(x <= y){
				// win1;
				// continue;
			// }else{
				// win2;
				// continue;
			// }
		// }
// 		
		// if(a.mei == 1 && b.mei == 1){
			// int x = 0x3f3f3f3f, y = 0x3f3f3f3f;
			// if(a.hui > b.xi) x = b.xi + 1;
			// if(b.hui > a.xi) y = a.xi + 1;
			// if(a.hui - b.hui + 1 >= b.xi) y = min(y, a.hui - b.hui + 1);
			// if(b.hui - a.hui + 1 >= a.xi) x = min(x, b.hui - a.hui + 1);
			// if(x == 0x3f3f3f3f && y == 0x3f3f3f3f){
				// Draw;
				// continue;
			// }
			// if(x <= y){
				// win1;
				// continue;
			// }else{
				// win2;
				// continue;
			// }
		// }
		
		int x = 0x3f3f3f3f, y = 0x3f3f3f3f;
		
		if(!b.mei && a.hui > b.xi) x = b.xi + 1;
		else if(b.mei && a.hui - b.hui > b.xi) x = b.xi + 1;
		
		if(!a.mei && b.hui > a.xi) y = a.xi + 1;
		else if(a.mei && b.hui - a.hui > a.xi) y = a.xi + 1;
		
		if(x == y && x == 0x3f3f3f3f){
			Draw;
			continue;
		}
		
		if(x <= y){
			if (b.hui >= x - 1 && x - 1 > a.xi){
				Draw;
				continue;
			}
			win1;
			continue;
		}
		else{
			if(a.hui > b.hui + 1 && a.hui >= y && y > b.xi){
				Draw;
				continue;
			}
			if(a.hui <= b.hui + 1 && a.hui >= y - 1 && y - 1 > b.xi){
				Draw;
				continue;
			}
			win2;
			continue;
		}
	}
    return 0;
}//by hwl

  • 14
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值