11.29~11.30日cf刷题记录

D. Radio Towers

codeforces 1452D

1600的题,分子菲波那契数列,分母2^n,然后求分子除分母对mod取余,费马小定理,
mod为质数,gcd(y,mod)==1
x/y%mod = x*y^(mod-2)%mod
代码为一个快速幂加一个定理:

int a[maxn];
ll qpow(ll a, ll b){
     
    ll res = 1;
    while(b>0){
     
        if(b&1) res = res*a%mod;
        b>>=1;
        a = a*a%mod;
    }
    return res;
}
signed main(){
     
    int n;
    scanf("%lld", &n);
    a[1] = 1, a[2] = 1, a[3] = 2;
    for(int i = 4; i <= n; i++){
     
        a[i] = a[i-2]+a[i-1];
        a[i] %= mod;
    }
    cout<<(a[n]*qpow(qpow(2,n), mod-2))%mod<<endl;
    return 0;
}

B. Catching Cheaters

codeforces 1446B

1800的题,通过这个题目复习了最长公共子序列,最长上升子序列。
最长公共子序列原本是可以用滚动数组来优化空间的,但实质上没有太大用处,毕竟如果卡了空间的话,时间也一定会被卡掉。
该题的主要意思是两个序列A,B,ans = 4*LCS(C,D)-|C|-|D|,最大化ans,显然的dp,或者说最长公共子序列做一些修改即可。

signed main(){
     
	int n, m;cin>>n>>m;
	scanf("%s%s", s1+1, s2+1);
	int ans = 0;
	for(int i = 1; i <= n; i++){
     
		for(int j = 1; j <= m; j++){
     
			if(s1[i]==s2[j]) dp[i][j] = max(dp[i][j], dp[i-1][j-1]+2);
			else dp[i][j] = max(dp[i][j], max(dp[i-1][j], dp[i][j-1])-1);
			ans = max(dp[i][j], ans);
		}
	}
	printf("%d\n", ans);
	return 0;
}

B. Identify the Operations

codeforces 1442B

1800的题,思维题,加看懂题意。
两个数组a,b,a中的元素为1到n,无重复,在a中进行k次操作(k为数组b长度),操作为删除一个数,然后可以选择其左右两边中的一个数放入栈中,同时数组a进行压缩,下标也随之改变,最后使得栈中的元素于数组b一一对应,问有多少种选择下标的方式。
思路是肯定是对数组b进行一遍遍历,在a中寻找位置,如果当前数在a中的位置左右两边都在之后b中出现那么没有方法能得到相应的b序列,与之对应的如果左边没有出现那么cnt++,右边没有出现也cnt++,得到最后的答案。

inline void cf(){
     
	int t;scanf("%lld", &t);
	while(t--){
     
		int n, m; scanf("%lld%lld", &n, &m);
		for(int i = 0; i < n; i++) vis[i] = p[i] = 0;
		for(int i = 0; i < n; i++) scanf("%lld", &a[i]), a[i]--, p[a[i]] = i;
		for(int i = 0; i < m; i++) scanf("%lld", &b[i]), b[i]--, vis[b[i]] = 1;
		int ans = 1;
		for(int i = 0; i < m; i++){
     
			int pos = p[b[i]], cnt = 0;
			if(pos-1>=0&&!vis[a[pos-1]]) cnt++;
			if(pos+1<n&&!vis[a[pos+1]]) cnt++;
			ans = ans*cnt%mod; 
			vis[b[i]] = 0; //进行更新
		}
		printf("%lld\n", ans);
	}
	return ;
}

你可能感兴趣的:(codeforces)