2020 ICPC 上海站

B : M i n e S w e e p e r I I \mathbf{B:Mine Sweeper II} B:MineSweeperII

题目大意

给你两个大小为 n ∗ m n * m nm 的扫雷图 A , B A, B A,B,要求通过最多 n ∗ m 2 \frac{n * m}{2} 2nm次转换(转换指 把一个不是雷的格子变成雷, 或者把一个是雷的格子变成空白格),使得 B图的值 和 A图的值相等(值 就是指 扫雷图上的所有数字之和,没有数字或者雷的地方的值为 0 0 0

分析

一个地雷对周围的影响,等价于把这个地雷改成空白,把周围的空白改成地雷,所以我们只需要求这个图的补图就可以了

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e3 + 10;
char a[N][N];
char b[N][N];
int n,m;

int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)
        scanf("%s",a[i] + 1);
    for(int i = 1;i <= n;i++)
        scanf("%s",b[i] + 1);
    int ans = 0;
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= m;j++)
            if(a[i][j] != b[i][j]) ans++;
    if(ans <= n * m / 2){
        for(int i = 1;i <= n;i++)
            printf("%s\n",a[i] + 1);
    }
    else{
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= m;j++)
                if(a[i][j] == '.') printf("X");
                else printf(".");
            puts("");
        }
    }
    return 0;
}

/**
*  ┏┓   ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃       ┃
* ┃   ━   ┃ ++ + + +
*  ████━████+
*  ◥██◤ ◥██◤ +
* ┃   ┻   ┃
* ┃       ┃ + +
* ┗━┓   ┏━┛
*   ┃   ┃ + + + +Code is far away from  
*   ┃   ┃ + bug with the animal protecting
*   ┃    ┗━━━┓ 神兽保佑,代码无bug 
*   ┃        ┣┓
*    ┃        ┏┛
*     ┗┓┓┏━┳┓┏┛ + + + +
*    ┃┫┫ ┃┫┫
*    ┗┻┛ ┗┻┛+ + + +
*/

C : S u m o f L o g \mathbf{C:Sum of Log} C:SumofLog

题目大意

给定 x , y x,y x,y,我们需要把在这里插入图片描述
给算出来

分析

这个问题可以转换成,一个范围内,当 i & j = = 0 i \& j == 0 i&j==0 的的情况下,二进制最高位的所有数的和,所以我们可以想到数位DP的做法
我们可以分两种情况来讨论,一种情况是当 i > j i > j i>j 的情况,这个时候 log ⁡ 2 ( i + j ) \log_2(i + j) log2(i+j)的值就是 i i i的二进制表示下最高位的位置,反过来再讨论 i < j i < j i<j 的情况即可

代码

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
#define _CRT_SECURE_NO_WARNINGS
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
const int INF = 0x3f3f3f3f;
const int N = 50;
const ll mod= 1000000007;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
int gcd(int a,int b){return (b>0)?gcd(b,a%b):a;}
ll f[N][2][2];
ll x,y;
int a[N],b[N];

ll dfs(int pos,bool sta,bool stb){
    if(!pos) return 1;
    if(f[pos][sta][stb] != -1) return f[pos][sta][stb];
    int ed1 = sta ? a[pos] : 1;
    int ed2 = stb ? b[pos] : 1;
    ll res = 0;
    for(int i = 0;i <= ed1;i++)
        for(int j = 0;j <= ed2;j++){
            if(j & i) continue;
            res = (res + dfs(pos - 1,sta && i == ed1,stb && j == ed2));
        }
    f[pos][sta][stb] = res;
    return res;
}

ll run(){
    int la = 0,lb = 0;
    memset(a,0,sizeof a);
    memset(b,0,sizeof b);
    while(x) {
        a[++la] = x & 1;
        x >>= 1;
    }
    while(y){
        b[++lb] = y & 1;
        y >>= 1;
    }
    ll res = 0;
    memset(f,-1,sizeof f);
    for(int i = la;i;i--){
        res = (res + dfs(i - 1,i == la,i > lb) * i) % mod;
    }
    memset(f,-1,sizeof f);
    for(int i = lb;i;i--){
        res = (res + dfs(i - 1,i > la,i == lb) * i) % mod;
    }
    return res;
}

int main(){
    int T;
    read(T);
    while(T--){
        read(x),read(y);
        dl(run());
    }
    return 0;
}

/**
*  ┏┓   ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃       ┃
* ┃   ━   ┃ ++ + + +
*  ████━████+
*  ◥██◤ ◥██◤ +
* ┃   ┻   ┃
* ┃       ┃ + +
* ┗━┓   ┏━┛
*   ┃   ┃ + + + +Code is far away from  
*   ┃   ┃ + bug with the animal protecting
*   ┃    ┗━━━┓ 神兽保佑,代码无bug 
*   ┃        ┣┓
*    ┃        ┏┛
*     ┗┓┓┏━┳┓┏┛ + + + +
*    ┃┫┫ ┃┫┫
*    ┗┻┛ ┗┻┛+ + + +
*/



D : W a l k e r \mathbf{D:Walker} D:Walker

题目大意

给你两个人的位置和速度,以及这段路程的总长度,问你最少多长时间两个人可以走完这整段路程

分析

分情况讨论即可
1. 1. 1.第一个人独自走完全程
2. 2. 2.第二个人独自走完全程
3. 3. 3.右边的人向左走左边的人向右走
4. 4. 4.最终在中间相遇,二分位置

代码

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
#define _CRT_SECURE_NO_WARNINGS
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 10;
const ll mod= 1000000007;
const double eps = 1e-10;
const double PI = acos(-1);
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
int gcd(int a,int b){return (b>0)?gcd(b,a%b):a;}
double v1,v2,p1,p2,n;
double res4;
int sgn(double x)
{
    if(fabs(x)<=eps)
        return 0;
    else if(x<0)
        return -1;
    else
        return 1;
}

bool check(double mid){
    double t1 = (min(mid - p1,p1) + mid)/ v1;
    double t2 = (min(p2 - mid,n - p2) + n - mid) / v2;
    res4 = min(res4,max(t1,t2));
    return sgn(t1 - t2) < 0;
}

int main(){
    int T;
    read(T);
    while(T--){
        cin >> n >> p1 >> v1 >> p2 >> v2;
        if(p1 > p2) swap(p1,p2),swap(v1,v2);
        double res1 = (min(n - p1,p1) + n) / v1;
        double res2 = (min(n - p2,p2) + n) / v2;
        double res3 = max((n - p1) / v1,p2 / v2);
        res4 = 1e9;
        double l = p1,r = p2;
        for(int i = 1;i <= 1000;i++){
            double mid = (l + r) / 2;
            if(check(mid)) l = mid;
            else r = mid;
        }
        printf("%.10lf\n",min(min(res1,res2),min(res3,res4)));
    }
    return 0;
}

/**
*  ┏┓   ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃       ┃
* ┃   ━   ┃ ++ + + +
*  ████━████+
*  ◥██◤ ◥██◤ +
* ┃   ┻   ┃
* ┃       ┃ + +
* ┗━┓   ┏━┛
*   ┃   ┃ + + + +Code is far away from  
*   ┃   ┃ + bug with the animal protecting
*   ┃    ┗━━━┓ 神兽保佑,代码无bug 
*   ┃        ┣┓
*    ┃        ┏┛
*     ┗┓┓┏━┳┓┏┛ + + + +
*    ┃┫┫ ┃┫┫
*    ┗┻┛ ┗┻┛+ + + +
*/



G : F i b o n a c c i \mathbf{G:Fibonacci} G:Fibonacci

题目大意

将当前斐波那契数分别与其后到 n n n的数相乘,值为偶数总和加一。

分析

签到题,找一下规律就可以了

代码

#include <iostream>

using namespace std;
typedef long long ll;

int main(){
	ll sum = 0;
	ll n;
	scanf("%lld",&n);
	sum = n / 3 * (n - 1) - (n / 3) * (n / 3 - 1) / 2;
	printf("%lld",sum);
}

M : G i t i g n o r e \mathbf{M:Gitignore} M:Gitignore

题目大意

给你一些文件夹和文件,文件夹没有空的,文件夹里面可能有文件和文件夹,有些文件是可以忽略的,有些文件是不能被忽略的,我们要找到最少的能被忽略的文件的个数。

分析

几个月后再看这道题发现,小丑竟是我自己
当时没学 a c ac ac自动机,可持久化 t r i e trie trie也是直接跳过直接学的主席树,导致差点都忘了字典树这个数据结构,最后用一种很复杂的存图方式把这棵树存下来,然后 d f s dfs dfs一下就可以了
来欣赏一下小丑的代码

代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
map<string,int> M;
int h[N],ne[N],e[N],idx;
int ppp[N][N];
int sum[N];
int son[N];
bool st[N];
int ans;
int num;
string str;
int n,m;

int find(string str){
	if(!M[str]) M[str] = ++num;
	return M[str];
}

void add(int x,int y){
	ne[idx] = h[x],e[idx] = y,h[x] = idx++;
}

void init(){
	memset(h,-1,sizeof h);
	memset(ppp,0,sizeof ppp);
	memset(sum,0,sizeof sum);
	memset(son,0,sizeof son);
	memset(st,0,sizeof st);
	M.clear();
	idx = 0,num = 0;
	ans = 0;
	scanf("%d%d",&n,&m);
}

void dfs(int u){
	if(h[u] == -1) son[u] = 1;
	for(int i = h[u];~i;i = ne[i]){
		int j = e[i];
		dfs(j);
		son[u] += son[j];
		sum[u] += sum[j];
	}
}

void qqqq(int u){
	// cout <<u << endl << ' '  <<son[u] << ' ' << sum[u] << endl;
	if(son[u] == sum[u]){
		// cout <<u << endl;
		// cout <<son[u] << ' ' << sum[u] << endl;
		ans++;
		return ;
	}
	for(int i = h[u];~i;i = ne[i]){
		int j = e[i];
		qqqq(j);
	}
}

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		init();
		int res = 0;
		for(int i = 1;i <= n;i++){
			cin >> str;
			string back = "";
			int last = 0;
			for(int j = 0;j < str.length();j++){
				if(str[j] == '/'){
					int xx = find(back);
					if(!ppp[last][xx]){
						ppp[last][xx] = ++res;
						add(last,ppp[last][xx]);
					}
					// cout <<last <<' ' <<ppp[last][xx] << endl;
					last = ppp[last][xx];
					back = "";
				}
				else{
					back = back + str[j];
				}
			}
			int xx = find(back);
			if(!ppp[last][xx]){
				ppp[last][xx] = ++res;
				add(last,ppp[last][xx]);
			}
			// cout <<last <<' ' <<ppp[last][xx] << endl;
			sum[ppp[last][xx]] = 1;
			back = "";
		}
		for(int i = 1;i <= m;i++){
			cin >> str;
			string back = "";
			int last = 0;
			for(int j = 0;j < str.length();j++){
				if(str[j] == '/'){
					int xx = find(back);
					if(!ppp[last][xx]){
						ppp[last][xx] = ++res;
						add(last,ppp[last][xx]);
					}
					// cout <<last <<' ' <<ppp[last][xx] << endl;
					last = ppp[last][xx];
					back = "";
				}
				else{
					back = back + str[j];
				}
			}
			int xx = find(back);
			if(!ppp[last][xx]){
				ppp[last][xx] = ++res;
				add(last,ppp[last][xx]);
			}
			// cout <<last <<' ' <<ppp[last][xx] << endl;

			back = "";
		}
		dfs(0);
		for(int i = h[0];~i;i = ne[i]){
			int j = e[i];
			if(st[j]) continue;
			st[j] = true;
			qqqq(j);
		}
		printf("%d\n",ans);
	}
}


猜你喜欢

转载自blog.csdn.net/tlyzxc/article/details/114542956