1. 程式人生 > >atcoder CODE FESTIVAL 2017 qual A 手速(霧)賽

atcoder CODE FESTIVAL 2017 qual A 手速(霧)賽

       這個比賽看起來好像挺重要的,,(結果來了一眾大佬誰都打不過qaq)

       A,B題不知道是幹什麼的

       C題(其實也是不知道在幹什麼)就是給一個字母矩陣,重排列後問是否能使它水平軸對稱+豎直軸對稱。

       可以發現一個矩陣最多由三部分組成:1.中心點,需要1個字母;2.中軸線,需要2個相同字母為1對填上去;3.其餘部分,需要4個相同字母為1組填上去。顯然能填3就能填2,能填2就能填1,因此考慮從3->2->1貪心放即可。

AC程式碼如下:

#include<bits/stdc++.h>
using namespace std;
 
int m,n,num[26]; char s[100009];
int main(){
	scanf("%d%d",&m,&n);
	int s1=(m>>1)*(n>>1),s2=(m&1)*(n>>1)+(m>>1)*(n&1),s3=m&n&1;
	int i,j;
	for (i=1; i<=m; i++){
		scanf("%s",s+1);
		for (j=1; j<=n; j++) num[s[j]-'a']++;
	}
	for (i=0; i<26; i++){
		while (num[i]>=4 && s1){ num[i]-=4; s1--; }
		while (num[i]>=2 && s2){ num[i]-=2; s2--; }
		while (num[i] && s3){ num[i]--; s3--; }
		if (num[i]) break;
	}
	puts(i<26?"No":"Yes");
	return 0;
}

          從D題開始才開始有含金量的題目,,(可能F題也不那麼難?),,然後我開場開了D題,看錯輸出格式爆了2發oj,,,啊難受

       題意就是給你m,n,d,要求構造一個染4色的方案,使得曼哈頓距離恰好為d的任何一對點顏色不同。

       首先考慮x+y->x,x-y->y,這樣就變成了以(x,y)為中心,邊心距為d的正方形的輪廓不能喝(x,y)同色。考慮x所在的行,我們可以採用先d個為一段,換一種顏色再d個為一段,再換回原來的顏色d個一段的方式染。這樣可以推廣到2維,考慮以一個d*d的正方形為一個單位,然後每4個的顏色兩兩不同,可以發現滿足條件。

AC程式碼如下:

#include<bits/stdc++.h>
using namespace std;
 
char ch[2][2]={{'R','B'},{'G','Y'}}; int n,m,k;
char calc(int x,int y){
	int a=x+y,b=x-y;
	a+=2000; b+=2000;
	a/=k; b/=k; a&=1; b&=1;
	return ch[a][b];
}
int main(){
	scanf("%d%d%d",&m,&n,&k);
	int i,j;
	for (i=1; i<=m; i++){
		for (j=1; j<=n; j++) printf("%c",calc(i,j)); puts("");
	}
	return 0;
}

          E題應該是唯一有一點難度的題目?,反正我可能是做了挺久的。

       E題題意為給你一個m*n的矩形,在矩形的四周有若干個人,每個人會向對面一直走,知道走到一個被染色的方格。然後在走的過程中他會把腳下的格子染成他自己的顏色。每個人顏色不同。求最後矩形的樣子有幾種。

       首先分上下/左右先走兩種情況。考慮上下先走,那麼會把矩形分成左右兩邊。並且可以發現如果最早走的是上下中的第x個和第y個,那麼x~y中間的就不能被左右的人走到了。所以可以考慮最早走的是第x~y個,然後左右的人再走。

      如果令f[i]表示走了i+1左邊的方案數,g[i]表示走了i-1右邊的方案數,那麼答案就是Σf[i]*g[j]*2^(s[j]-1-s[i])=Σ(f[i]/2^s[i])*(g[j]*2^s[j-1]),其中s[i]表示1~i中有幾個是上下都有人的。因此關鍵是求出f[i],同樣考慮左邊的先走的是a~b,那麼答案就是C(a+c,a)*C(b+d,b),其中c,d表示前i列中上、下個有多少人。考慮C(a+c,a)表示的是用(0,0)走到(a,c)的方案書,那麼可以發現答案等價於從(0,0)走到(c+d,t),並且在第c列必須走至少一步向上的方案數,其中t表示左邊有幾個人。所以答案就是C(c+d+t,t)-C(c+d-1+t,t)。

       最後小心特判全0的情況

AC程式碼如下:

#include<bits/stdc++.h>
#define N 400009
#define ll long long
#define mod 998244353
#define cbn(x,y) ((ll)fac[x]*inv[y]%mod*inv[(x)-(y)]%mod)
using namespace std;
 
int m,n,a[N],b[N],fac[N],inv[N]; char A[N],B[N],C[N],D[N];
int solve(int m,int n,char *A,char *B,char *C,char *D){
	int i,x,y;
	memset(a,0,sizeof(a)); memset(b,0,sizeof(b));
	a[0]=b[n+1]=1;
	for (i=1,y=0; i<=m; i++) if (A[i]=='1') y++;
	for (i=1,x=0; i<=n; i++){
		if (C[i]=='1') x++;
		if (D[i]=='1') x++;
		a[i]=cbn(x+y,x);
		if (x) a[i]=(a[i]-cbn(x+y-1,x-1)+mod)%mod;
		//cout<<i<<' '<<a[i]<<endl;
	}
	for (i=1,y=0; i<=m; i++) if (B[i]=='1') y++;
	for (i=n,x=0; i; i--){
		if (C[i]=='1') x++;
		if (D[i]=='1') x++;
		b[i]=cbn(x+y,x);
		if (x>0) b[i]=(b[i]-cbn(x+y-1,x-1)+mod)%mod;
		//cout<<i<<' '<<b[i]<<endl;
	}
	int tmp;
	for (i=0,tmp=1; i<=n; i++){
		if (i>0 && C[i]=='1' && D[i]=='1') tmp=(ll)tmp*(mod+1>>1)%mod;
		a[i]=(ll)a[i]*tmp%mod;
		if (i<=n && C[i+1]=='0' && D[i+1]=='0') a[i]=0;
	}
	for (i=1; i<=n; i++) a[i]=(a[i]+a[i-1])%mod;
	for (i=tmp=1; i<=n+1; i++){
		b[i]=(ll)b[i]*tmp%mod;
		if (i<=n && C[i]=='1' && D[i]=='1') tmp=tmp*2%mod;
		if (i>1 && C[i-1]=='0' && D[i-1]=='0') b[i]=0;
	}
	int ans=0;
	for (i=1; i<=n; i++) ans=(ans+(ll)b[i+1]*a[i-1])%mod;
	//cout<<ans<<endl;
	return ans;
}
int main(){
	scanf("%d%d",&m,&n);
	scanf("%s%s%s%s",A+1,B+1,C+1,D+1);
	int i;
	for (i=1; i<=m; i++) if (A[i]=='1' || B[i]=='1') break;
	if (i>m){
		for (i=1; i<=n; i++) if (C[i]=='1' || D[i]=='1') break;
		if (i>n){ puts("1"); return 0; }
	}
	fac[0]=inv[0]=inv[1]=1;
	for (i=1; i<=(m+n<<1); i++) fac[i]=(ll)fac[i-1]*i%mod;
	for (i=2; i<=(m+n<<1); i++) inv[i]=mod-(ll)inv[mod%i]*(mod/i)%mod;
	for (i=2; i<=(m+n<<1); i++) inv[i]=(ll)inv[i-1]*inv[i]%mod;
	printf("%d\n",(solve(m,n,A,B,C,D)+solve(n,m,C,D,A,B))%mod);
	return 0;
}

            最後的F題似乎比E題簡單多了。。我A掉E發現F已經過了一片了,qaq

        F就是已知一個若干個1構成的序列,然後每次可以選擇2n個連續的數,按照(1,2)(3,4),...(2n-1,2n)的方式合併,得到最終的序列。現在告訴你最終的序列,求最少幾步。

        顯然應該倒過來做。那麼考慮一次操作就是把連續的若干>1的數拆成兩半,顯然應該貪心地拆成均勻的兩份。那麼考慮拆x的過程中,每一步之後都是由兩部分組成,一部分都是t,另一部分都是t+1。

        然後考慮原問題。顯然產生的1會將原問題分成兩個子問題。顯然最小的數最早產生1,那麼把原問題分成兩個問題之後遞迴地做。注意到最小的數產生1之後可能還有部分2,需要列舉放在左邊還是右邊。

AC程式碼如下:

#include<bits/stdc++.h>
#define N 100009
using namespace std;
 
int n,a[N],lg2[N];
struct node{ int x,y; }f[17][N],b[N];
struct matrix{ int p[2][2]; };
bool operator <(node u,node v){ return u.x<v.x; }
int getmin(int x,int y){
	int k=lg2[y-x+1];
	//cout<<"	"<<x<<' '<<y<<endl;
	//cout<<k<<' '<<x<<' '<<y<<' '<<f[k][x].y<<' '<<f[k][y-(1<<k)+1].y<<endl;
	return min(f[k][x],f[k][y-(1<<k)+1]).y;
}
void calc(int k){
	int flag=0,i=a[k];
	for (; i>1; i>>=1){
		b[k].x++;
		if (i&1) flag=1;
	}
	b[k].y=flag;
}
matrix solve(int l,int r,int dep){
	//cout<<l<<' '<<r<<endl;
	if (l>r){
		matrix x;
		x.p[0][0]=0; x.p[0][1]=x.p[1][0]=x.p[1][1]=1;
		return x;
	}
	int mid=getmin(l,r),i,j,k,x=b[mid].x,y=b[mid].y;
	matrix u=solve(l,mid-1,x),v=solve(mid+1,r,x),z;
	for (i=0; i<2; i++)
		for (j=0; j<2; j++){
			z.p[i][j]=1000000000;
			for (k=0; k<=y; k++) z.p[i][j]=min(z.p[i][j],u.p[i][k]+v.p[y-k][j]);
		}
	//cout<<l<<' '<<r<<' '<<mid<<' '<<x<<' '<<dep<<endl;
	for (i=0; i<2; i++)
		for (j=0; j<2; j++) z.p[i][j]+=x-dep;
	if (dep<x)
		for (i=0; i<2; i++)
			for (j=0; j<2; j++) z.p[i][j]=z.p[0][0];
	//for (i=0; i<2; i++)
		//for (j=0; j<2; j++) cout<<z.p[i][j]<<' ';puts("");
	return z;
}
int main(){
	scanf("%d",&n);
	int i,j;
	for (i=2; i<=n; i++) lg2[i]=lg2[i>>1]+1;
	for (i=1; i<=n; i++){
		scanf("%d",&a[i]); calc(i);
		//cout<<i<<' '<<b[i].x<<' '<<b[i].y<<endl;
	}
	for (i=1; i<=n; i++) f[0][i]=(node){a[i],i};
	for (i=1; i<=16; i++)
		for (j=1; j<=n; j++){
			f[i][j]=f[i-1][j];
			if (j+(1<<i-1)<=n) f[i][j]=min(f[i][j],f[i-1][j+(1<<i-1)]);
		}
	printf("%d\n",solve(1,n,0).p[0][0]);
	return 0;
}


by lych

2017.9.25

相關推薦

atcoder CODE FESTIVAL 2017 qual A

       這個比賽看起來好像挺重要的,,(結果來了一眾大佬誰都打不過qaq)        A,B題不知道是幹什麼的        C題(其實也是不知道在幹什麼)就是給一個字母矩陣,重排列後問是否

CODE FESTIVAL 2017 qual A C Palindromic Matrix思維題

int 字母 esp != 題意 nbsp class task col 題目鏈接:點我呀 題意:給出n*m由26位小寫字母組成的矩陣,問是否能夠重構形成一個每行每列都是回文的矩陣 題解:分三種情況考慮(偶偶,奇奇,奇偶),每種情況下考慮最少 需要4個相同字母的字母數,

CODE FESTIVAL 2017 qual A--C - Palindromic Matrix(模擬所有情況,註意細節)

需要 tip stream pac pos ear war sample element 個人心得:其實本來這題是有規律的不過當時已經將整個模擬過程都構思出來了,就打算試試,將每個字符和總和用優先隊列 裝起來,然後枚舉每個點,同時進行位置標誌,此時需要多少個點的時候拿出最大

Atcoder Code Festival 2017 qual C 10.22 D題題解

最小 display val sed hide min clas closed urn 【題意概述】 給出一個只有小寫字母的序列,問最少把序列分成幾段可以滿足每一段可以通過變換成為回文串。變換指的是交換子序列中的字母的位置。 【題解】 我們把a~z分別設為2^0~2

atcoder CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning

absolut tom per cas data- lose som coder none Problem Statement We have a string s consisting of lowercase English letters. Snuke is par

[Atcoder Code Festival 2017 Qual B Problem F]Largest Smallest Cyclic Shift

can esp using ins str small highlight div turn 題目大意:給你\(A\)個a,\(B\)個b,\(C\)個c,要你構造一個字符串,使它的最小循環表示法最大。求這個表示法。解題思路:不知道怎麽證,但把a、b、c當做單獨的字符串扔進

101 to 010 Atcoder CODE FESTIVAL 2017 qual B D

hide clas bsp img 技術 return org include blog https://www.luogu.org/problemnew/show/AT3575 題解 根本不會。。 錯誤記錄:缺少32行的轉移。顯然這個轉移是必要的 1 #

AtCoderCODE FESTIVAL 2017 qual C

pac fde long cpp part 平安 mod set -c A - Can you get AC? No #include <bits/stdc++.h> #define fi first #define se second #define pii

AtCoderCODE FESTIVAL 2017 qual B

date cpp b- 但是 sca dfs utc scanf || 最近不知道為啥被安利了饑荒,但是不能再玩物喪誌了,不能頹了 饑荒真好玩 A - XXFESTIVAL CCFESTIVAL #include <bits/stdc++.h> #define

CODE FESTIVAL 2017 qual B 解題報告

pop cnblogs min air 坐標 第一次 最大 com type 做atcoder總是感到格外的智商不足……感覺atcoder比起codeforces來說題目普遍更有趣,更考驗思維orz C 題意:給出無向圖,距離為3的點如果未連邊,則可以連上一條邊,問最多能連

CODE FESTIVAL 2017 qual C F

blog ges images .com img 1-1 .cn 分享 技術分享 以上為官方題解..CODE FESTIVAL 2017 qual C F

[CODE FESTIVAL 2017 Final H]Poor Penguin

滿足 更新 style i++ class tco sca stdio.h 我們 題意:在一個$n\times m$的網格上,每個格子是薄冰或冰山(網格外什麽都沒有),有一片薄冰上站著一只企鵝,對於薄冰$(i,j)$,如果不滿足($(i-1,j),(i+1,j)$都有東西或

[CODE FESTIVAL 2016 Exhibition A]Distance Pairs

lse 不錯 esp ont i++ main distance 似的 std 題意:有一個未知的邊權為$1$的圖,給定所有點到$1$的最短路$a_i$和到$2$的最短路$b_i$,問是否存在這樣的圖,如果存在,問圖中最少有多少條邊 先考慮$a_i$,有$a_1=0,a_

Atcoder CODE FESTIVAL 2016Final G:Zigzag MST

傳送門 題解: 把邊掰到環上,然後取min,就只有O(n)O(n)O(n)條邊了。 #include <bits/stdc++.h> using namespace std; const

AtCoder Code festival 2017qualC-D-dp+優化

傳送門 題意: 給你一個字串s,問s最少分成幾塊,使得每一塊在經過組合後都能成為一個迴文串。(|s|≤2e5) Solution: 我們可以轉化一下“迴文串”這個定義,對於每個字母我們可以把它分

Code Festival 2017 qualA D Four Coloring[構造]

Description 題意是給定一個H∗W的網格,和一個整數d。 要求將這些網格染成四種顏色,使得曼哈頓距離恰好為d的點對的顏色不同。 Solution 看到曼哈頓距離就要想到和切比雪夫距

NYOJ 1128 雙端佇列

題目1128 手速 時間限制: 1000 ms  |  記憶體限制: 65535 KB 難度: 1 描述

無聊的程式設計師教你如何使用十幾行程式碼練就單身20年的文末彩蛋

故事背景 友女回家學車,今天星期五,明天不上班。 正文開始 作為一個程式設計師,在無聊的時候會做點什麼呢?大多數的都是會選擇玩遊戲,今晚我也選擇了一個遊戲,這個遊戲叫反應速度大比拼,如下圖 玩法特別簡單,就是當你點選開始按鈕後,如果看到背景顏色變

atcoder A - Frog 1DP

A - Frog 1 Time Limit: 2 sec / Memory Limit: 1024 MB Score : 100100 points Problem Statement There are NN stones, numbe

AtCoder Grand Contest 032 A - Limited Insertion 思維

operation ems gcd text The tint type lse base Time Limit: 2 sec / Memory Limit: 1024 MB Score : 400400 points Problem Statement Sn