第45回国際大学学生プログラミングコンペティション(ICPC)アジア地域コンペティション(南京)
B:マインスイーパーII \ mathbf {B:マインスイーパーII} B:M i n e S w e e p e r I I
一般的なアイデア
n ∗ mn * mの2つのサイズを与えますn∗mの地雷除去マップA、BA、BA 、B、最大でn ∗ m 2 \ frac {n * m} {2}を通過する必要があります2N *メートル2番目の変換(変換とは、雷ではないグリッドを雷に変えること、または雷であるグリッドを空白のグリッドに変えることを指します)。これにより、B画像の値はA画像の値と等しくなります(値は掃海図のすべての数字を指します)そして、数字や雷がない場合、値は00です。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 umof L og \ mathbf {C:Sum of Log} C:S u m o f L o g
一般的なアイデア
与えられたx、yx、yx 、yは、我々は必要
把握します
分析
この質問は、i&j = = 0 i \&j == 0の場合、範囲内で変換できます。i &j==0の場合、最も高い2項位置にあるすべての数値の合計であるため、デジタルDPの実践を考えることができます
。2つの状況で議論できます。1つはi> ji> jの場合です。私>>jの場合、この時点でlog2(i + j)\ log_2(i + j)lo g2(私は+j )の値はiiですiの2進数は、最下位ビットの位置を表します。次に、i <ji <jについて説明します。私<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:ウォーカー\ mathbf {D:ウォーカー} D:W a l k e r
一般的なアイデア
2人の位置と速度、および旅の全長を教えてください。また、旅全体を完了するのに少なくとも2人がかかる時間を尋ねてください。
分析
状況ごとに話し合うのは
1.1です。1 。最初の人だけでは全体の旅
2.2。2 。一人で二人目の全体の旅
3.3。3 。人々は左に行く右へ右の人々の左に行く
4.4。4 。最終的に、中央で2つの場所を満たします
コード
#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:フィボナッチ\ mathbf {G:フィボナッチ} G:F i b o n a c c i
一般的なアイデア
現在のフィボナッチ数を以下からnnに分離しますnの数が乗算され、値は偶数と1の合計です。
分析
サインインの質問、ルールを見つけるだけ
コード
#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 itignore \ mathbf {M:Gitignore} M:G i t i g n o r e
一般的なアイデア
いくつかのフォルダとファイルがあります。フォルダは空ではありません。フォルダ内にファイルとフォルダがある可能性があります。無視できるファイルと無視できないファイルがあります。無視できるファイルの数を最小限に抑える必要があります。番号。
分析
数か月後にもう一度この質問を調べたところ、ピエロは実際には自分自身であることがわかりまし
た。当時、私はacacを学びませんでした。a cオートマトン、トライトライを持続させることができますtはrを私は電子も椅子ツリーが直接学び、ほとんどの辞書の木のデータ構造を忘れてしまった、そして最終的には非常に複雑な画像の保存方法でツリーを保存し、その後、スキップDFSをDFSd f sは
少しだけ行います、ピエロのコードを楽しみましょう
コード
#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);
}
}