CF1499

CF1499

A:Domino on Windowsill

对于一个任意 \(2*2\) 的矩形,都是最多放两个。

定义 \(mini=min(k_1,k_2)\)

这时我们发现,无论 \(mini\) 是奇数还是偶数,化简后的 \(ans\) 都是 \(min(k_1,k_2)+(abs(k_1-k_2)/2)\)

那么白色部分就解决了,黑色的话实际上也是一样的,只是 \(k_1\) 变成 \(n-k_1\)\(k_2\) 变成 \(n-k_2\),化简后就是 \(min(n-k_1,n-k_2)+(abs(k_1-k_2)>>1)\)

#include<bits/stdc++.h>
using namespace std;
int T;
int n,k1,k2,w,b;
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d%d%d",&n,&k1,&k2,&w,&b);
		int a1=min(k1,k2)+(k1+k2-2*min(k1,k2))/2,
			a2=min(n-k1,n-k2)+(2*n-k1-k2-min(n-k1,n-k2)*2)/2;
		if(a1>=w&&a2>=b)printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

B: Binary Removals

想要出现否的情况那一定会有 \(0\)\(1\) 的后面,

而我们的删除操作只能隔着删,所以当出现两个 \(00\) 或两个 \(11\) 必然会留下一个

因此从后往前遍历,如果发现出现 \(00\) 之后又出现 \(11\) ,则最终无论怎么删都会留下一个 \(…1…0…\) 的情况。

模拟这个过程,即算出答案。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e6 + 5;
ll ji[N], o[N], sum[N];
int T; string str;
int main(){
	cin>>T;
	while(T--){
	    cin>>str; int f=1;
		for(int i=str.size()-2;i>=0;i--){
			if(f) {if(str[i]=='0'&&str[i+1]=='0') f=0;}
			else if(f==0)
				if(str[i]=='1'&&str[i+1]=='1'){
					cout<<"NO"<<endl;
					f=999; break;
				}
			
		}
		if(f!=999)cout<<"YES"<<endl;
	}
    // system("pause");
    return 0;
}

C:

贪心的考虑,我们需要让第一和第二小的线段一个向上一个向右尽量长,只需要枚举。

但是由于每一次有一个需要拐弯的性质,我们需要分为奇偶讨论。

分别记录奇偶前面的最小的 \(cost\) ,让奇数线段向上,偶数线段向右,其余线段长度都为 \(1\) ,剩下长度直接最小 \(cost\) 线段走完即可。

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=1e6+5;
ll ji[N],o[N],sum[N];
int T,n;
int main(){
    cin>>T;
    while(T--){
        cin >> n;
		ll ans=1e18;
		ji[0]=1e18, o[0]=1e18;
		for (int i=1;i <= n;i++){
			ll a;cin >> a;
			sum[i]=sum[i-1]+a;
			ji[i]=ji[i-1], o[i]=o[i-1];
			if (i%2==1)ji[i]=min(a, ji[i-1]);
			else o[i]=min(o[i-1], a);
		}
		for (int i=2;i <= n;i++){
			ll p;
			if (i%2==0)	p=sum[i]+ji[i]*(n-i/2)+o[i]*(n-i/2);	
			else p=sum[i]+ji[i]*(n-i/2-1)+o[i]*(n-i/2);
			ans=min(ans, p);
		}
		cout << ans << endl;
    }
    return 0;
}

D:

\(w=gcd(a,b)\),\(a∗b=w^2∗t\)

所以上式子可以转化为: \((c∗t−d)∗w=x\)

枚举 \(x\) 的因子,然后求出 \(t\) ,最后判断 \(t\) 有多少种质因子即可。

因为 \(t\) 的质因子只能给 \(a\) 或者 \(b\) ,假设最后有 \(m\) 个质因子,那么答案就是 \(2^m\)

#include <bits/stdc++.h>
using namespace std;
const int N = 2e7 + 1;
typedef long long ll;
int isp[N],cnt,v[N],dp[N],T;//dp[i] 表示组成 i 的质因子的种类
ll p[100];
void init() {
    cnt = 0;
    memset(v, 0, sizeof(v));
    for (int i = 2; i < N; i++) {
        if (!v[i])  v[i] = i,isp[cnt++] = i;
        for (int j = 0; j < cnt; j++) {
            if (1ll * i * isp[j] >= N) break;
            v[i * isp[j]] = isp[j];
            if (i % isp[j] == 0) break;
        }
    }
    for (int i = 2; i < N; i++) {
        int x = i;
        while (x % v[i] == 0) x /= v[i];
        dp[i] = dp[x] + 1;
    }
    p[0] = 1;
    for(int i=1;i<=60;i++) p[i] = p[i-1]*2;
}
int c,d,x;
ll solve(int res){
    int u =  res + d;
    if(u%c==0) return p[dp[u/c]];
    return 0;
}

int main() {
    init();
    scanf("%d", &T);
    while (T--) {
        ll ans = 0;
        scanf("%d%d%d", &c, &d, &x);
        for (int i = 1; i * i <= x; i++) {
            if (x % i == 0) {
                ans += solve(x / i);
                if (x / i != i) ans += solve(i);
            }
        }
        printf("%lld\n", ans);
    }
    // system("pause");
    return 0;
}
posted @ 2021-09-08 19:53  Evitagen  阅读(29)  评论(0编辑  收藏  举报