【模擬賽】2019.9.23—2019.9.24

背景:

模擬賽定下來了,,週一週二週五,週三討論,這晚自習佔的,一看課表發現週三週四是語文和英語晚自習,這還是不停課嗎???白天的課,能()上的就上(主要上理科和數學,,語文英語基本沒上過,,,結果就被KK懟回去上文化課了,結果發現好多不好補回來,但是沒有大片的空白,就是那些老師拓展的東西沒有學到,有點虧了,還有作業,基本沒寫,就是偶爾自己閒了就寫寫題當做休息,,這樣怎麼可能提高文化課,,,)這文化課啊,還是要好好學的,畢竟競賽不是上學的唯一途徑,但,高考是。

不瞎扯了來好好看題,,,

題目:


Day 1 題目:

T1: 硬幣求和(scoins)

簡化題目:

i=1n12i\sum_{i=1}^{n} \frac{1}{2\sqrt{i}}。(答案誤差不超過 ±1\pm1

(就是這麼直接,,)

題解:

(這個題,總用時15分鐘,然後就A掉了,,,神奇吧,,前10分鐘在看題,結果發現,並沒有什麼有用的文字描述,都是些水話,一點都麼沒有用,看到樣例後面的樣例解釋我才差不多能看懂,,然後就試了試大樣例,可以確定是個結論題,然後就直接隨便寫了個結論,結果就A了,,,又一次的小凱的疑惑啊,神奇!)

還是要好好看正解:
i=1n12i=12(1i) \sum_{i=1}^{n} \frac{1}{2\sqrt{i}}=\frac{1}{2}*(\frac{1}{\sqrt{i}})
要求出來這個答案,可以從1i\frac{1}{\sqrt{i}} 這裏下手。

從高中的放縮得到常見不等式:
2(n+1n)=2n+1+n<1n<2n+n1=2(nn1) 2*(\sqrt{n+1}-\sqrt{n})=\frac{2}{\sqrt{n+1}+\sqrt{n}}<\frac{1}{\sqrt{n}}<\frac{2}{\sqrt{n}+\sqrt{n-1}}=2*(\sqrt{n}-\sqrt{n-1})
可以知道:
i=1n2i+i+1<i=1n1i<i=n12i+i1 \sum^{n}_{i=1}\frac{2}{\sqrt{i}+\sqrt{i+1}}<\sum^{n}_{i=1}\frac{1}{\sqrt{i}}<\sum^{1}_{i=n}\frac{2}{\sqrt{i}+\sqrt{i-1}}
從左邊的最小值推出:
i=1n2i+1+i=2i=1n(i+1i)=2(n+11) \sum_{i=1}^{n}\frac{2}{\sqrt{i+1}+\sqrt{i}}=2*\sum_{i=1}^{n}(\sqrt{i+1}-\sqrt{i})=2*(\sqrt{n+1}-1)
從左邊的最大值推出:
i=n12i1+i=2i=n1(ii1)=2n \sum_{i=n}^{1}\frac{2}{\sqrt{i-1}+\sqrt{i}}=2*\sum_{i=n}^{1}(\sqrt{i}-\sqrt{i-1})=2*\sqrt{n}
再乘上剛開始的12\frac{1}{2},範圍就是:
(n+11,n) (\sqrt{n+1}-1,\sqrt{n})
QED.

但是我考場上吧,直接寫了個n1\sqrt{n}-1 ,然後就A掉了,這個其實是因爲n1\sqrt{n}-1 雖然不在(n+11,n)(\sqrt{n+1}-1,\sqrt{n})的範圍內,但是可以卡在±1\pm1裏面的,這個自行證明吧。(然後就用掉了我之前攢的所有RP,,)

```
#include<bits/stdc++.h>
#define int long long
#define over(i,s,t) for(int i=s;i<=t;i++)
#define lver(i,t,s) for(int i=t;i>=s;i--)
using namespace std;
inline int read()
{
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')ch=getchar();}
	while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();
	return s*w;
}
signed main()
{
//	freopen("scoins.in","r",stdin);
//	freopen("scoins.out","w",stdout); 
	int n=read(), c=sqrt(n+1.9); 
	int ans=0; if(c*c>n+1) ans=1; 
	printf("%lld\n",c-ans-1);
    //自己的一行AC代碼:(從此RP-ocean;)
    //int n=read();printf("%lld",sqrt(n)-1); 
	return 0;
}

T2:漢諾塔(hanoi)

簡化題目:

nn個盤子mm個柱子的漢諾塔問題。(nm<=1500n,m<=1500

題解:

(這個題,一上去我就知道這個爆搜我是絕對寫不出來的,然後就只寫了m=3m=3的情況,並沒有推出來最終的遞推式,,,結果想着是能拿20分的,結果,,,215002^{1500},,所以,,蒙了,,高精!!!,不是說好了不考高精的嘛!!!我就直接沒有學~~555555555哭死在角落,,,)

正解:
f[n][m]=min0k<n{2f[n][m]+f[nk][m1]} f[n][m] = \min_{0 \le k \lt n} \lbrace 2f[n][m] + f[n-k][m-1] \rbrace
這個是表示你在取kk個盤子的時候是會把它們放在mm個柱子上的,然後就在把剩下的盤子放在m1m-1個柱子上,然後再把之前的盤子放到最後一個柱子上,由於是取kk個盤子,所以方案數最後要取minmin

當你找到正確的遞推式之後就會發現這彷彿是一個O(n3)O(n^3)的寫法,所以呢,要優化啊!當你在取k個盤子的時候你會發現,如果n越大,k就會越大(這一點也可以打表看出來,打出來好像是個斜放的楊輝三角,是LDY大佬發現的,,,tql)然後kk就符合這個單調性所以就可以用單調指針進行優化。

代碼:

(由於ex的高精,我就寫了主要的那部分代碼,,,)

#include <bits/stdc++.h>
using namespace std;
#define MAXN 1500
#define ll unsigned long long
#define INFLL 0x3f3f3f3f3f3f3f3fllu
#define rint register int
inline int rf(){int r;int s=0,c;for(;!isdigit(c=getchar());s=c);for(r=c^48;isdigit(c=getchar());(r*=10)+=c^48);return s^45?r:-r;}
int n, m, T; ll f[MAXN+5][MAXN+5]; 
vector<int> A[MAXN+5];
inline void Mul2(vector<int> &A)
{
	A.push_back(0); A[0]*=2; 
	for(int i=1;i<(int)A.size();i++) A[i]=(A[i]<<1)+A[i-1]/10,A[i-1]%=10; 
	if(!A.back()) A.pop_back();
}
int main()
{
//	freopen("hanoi.in","r",stdin); 
//	freopen("hanoi.out","w",stdout);
	n=MAXN; m=MAXN; A[1].assign(1,2); 
	for (int i=2; i<=n; ++i)
	{
		A[i]=A[i-1],--A[i-1][0]; 
		Mul2(A[i]);
	}
	--A[n][0];
	
	memset(f,0x3f,sizeof f); memset(f[1]+1,0,n<<3);
	f[2][1]=1;  ll s=2;
	for(rint i=1;i<=n;i++)
	{
		f[3][i]=min(f[3][i],s-1);
		s = min(s<<1,INFLL+1);
	}
    //我碼的在這裏!!(卑微的摻雜在衆多高精處理之中,,,,)
	for(int i=4;i<=m;i++)
	{
		f[i][1]=1;
		for(int j=2;j<=n;j++)
		{
			int k=1;
			f[i][j]=2*f[i][k]+f[i-1][j-k];
			while (k+1<j&&2*f[i][k]+f[i-1][j-k]>2*f[i][k+1]+f[i-1][j-k-1]) k++;
            //這裏用單調指針進行優化,如果k的答案>k+1的答案而且k和k+1存在就k++往下查。
		}
	}
	
	
	T=rf();
	while(T--)
	{
		n = rf(); m = rf(); 
		if(m==1){puts("0"); continue;} 
		else if(m==2){puts(n>1?"No Solution":"1"); continue;}
		else if(m==3)
		{	
			for(rint i=A[n].size()-1;~i;i--) putchar(A[n][i]+'0');
			putchar('\n'); 
			continue;
		} 
		else printf("%llu\n",f[m][n]);
	}	
	return 0;
}

T3:隨機子樹(tree)

簡化題目:

求在[L,R][L,R]區間的子樹聯通塊的個數。

題解:

(這個題,我由於沒好好看題,沒注重子樹這個東西,然後就直接找的每兩個點的樹上距離,然後就死也想不到怎麼過樣例中的[3,5][3,5]然後就掛掉了,好像調了快兩個小時,,這就告訴我,要好好看題啊~~555555哭死在角落)

正解:

(表示這個題我只會到O(n3)O(n^3)的做法,還有O(n2)O(n^2)的方程式優化部分,,就會這麼多,後面要用到長鏈剖分+線段樹+樹形DP的大工程我就不參與了吧,,,這太難了,,等打完CSP再說,,)

由於求直徑大於一個值不太好做,但是直徑小於一個值還是比較好做的,先只考慮直徑在[1,R][1,R]區間的聯通塊個數。這就類似於直徑的DP式了,f[p][d]f[p][d]表示以點p爲最淺的點,最深點距離點p的深度爲d的聯通塊個數。進行樹形DP,將一個新兒子v加入的時候就是:
f[p][max(d1,d2+1)]=d1+d2+1<=Rf[p][d1]×f[v][d2] f'[p][max(d_1,d_2+1)]=\sum_{d_1+d_2+1<=R}f[p][d_1]\times f[v][d_2]
然後可以想辦把max優化掉,就可以分類討論,枚舉d2d_2:
f[p][d2+1]+=(d1+d2+1R,d1d2f[p][d1])×f[v][d2]f[p][d1]+=d1+d2+1R,d1>d2f[p][d1]×f[v][d2] f'[p][d_2+1] += \left( \sum_{d_1+d_2+1 \le R, d_1 \le d_2} f[p][d_1] \right) \times f[v][d_2] \\f'[p][d_1] += \sum_{d_1+d_2+1 \le R,d_1 \gt d_2} f[p][d_1] \times f[v][d_2]
這樣就可以用一個前綴和優化就好吧第一個式子搞掉了,但第二個,,,要用線段樹,,菜雞不想寫了,,,,太菜了。。

(說明一下:由於本菜雞太菜,不會自己寫dp時及其解釋,就直接搬題解了,但是在本博客中出現的菜雞是讀懂了的,剩下的就不會了。)

代碼:

(由於不會寫,所以就沒打算訂正代碼,,,,(卑微))

Day1總結:

第一要說的就是看懂題,好好讀懂題,你纔會發現其實你之前的一大堆思想就是個假算法,,就是在瞎扯,,,還是要好好讀題,多推幾遍樣例是不會浪費太多時間的,所以,還是那句話,讀懂題你才知道自己是否在通往得分的路上,否則你一走偏,就從此和OI無緣了,,,還有就是,,要吐槽一下這個高精,,,真的,剛學OI的時候就學到了高精,但老師那個時候就說高精不考不用學了,知道就好了,,所以,我就很聽話的過了一年,,然後到現在就一點也不會高精,也沒有想到會用到高精,這是真的有意思,之前的所有模擬賽都沒有過高精,我還特地去翻了前幾年的真題結果也是沒有高精啊!!!但是打完這場之後老師就又說可能考了,,,~~5555555555哭死o(╥﹏╥)o,,還是抽時間學一下吧。還有就是今天的RPRP由於過度使用,估計近期的考試都死掉了吧,,,,(ㄒoㄒ)


Day2題目:

T1:括號序列(bracket)

簡化題目:

給你一個括號串,求出合法的括號子串的個數。

題解:

(這個題啊,剛看懂題就大驚了,這不就是2017年noip的原題《時間複雜度》的極簡版嗎,而且是沒有REE的情況,就是開個棧就好了,,,但是,,(ㄒoㄒ)一個莫名其妙的原因,直接掛掉了,不知道爲什麼,結果是少考慮了一種情況,然後就完了,,100分啊,,沒有了,,這要是正式考試,我就只能死回去學文化課了,,,o(╥﹏╥)o)

正解:

神奇的是這個題,,,竟然有O(nn)O(n\sqrt{n})的優化型爆搜,O(nlog(n))O(nlog(n))的lower_bound的神奇做法,真的是強啊~~

這個題確實就是一個棧就跑過了,開個棧,如果是"("就進棧,不是就判斷,如果這個"()""()"前面什麼都沒的話就加上 11(自身的貢獻),不是的話就加上之前的貢獻,再加上自身的貢獻 11,對於括號只有兩種可能,一種是嵌套的,一種就是就地並列的,所以可以對每個單括號寫第二個結構體,每次可以記錄一下嵌套的個數,這樣的話方便統計答案。

代碼:

#include<bits/stdc++.h>
#define over(i,s,t) for(int i=s;i<=t;i++)
#define lver(i,t,s) for(int i=t;i>=s;i--)
using namespace std;
inline int read()
{
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();
	return s*w;
}
const int sea=1e6+7;
char ch[sea],s[sea];
int n,top=0,ans,b[sea];
struct hit{int x,sum;}a;
stack<hit>st;
int main()
{
//	freopen("bracket.in","r",stdin);
//	freopen("bracket.out","w",stdout);
	cin>>ch; n=strlen(ch); 
	over(i,1,n) s[i]=ch[i-1];  int num=ans=0;
	over(i,1,n)
	{
		if(s[i]=='(') a.x=1;else a.x=2;
		if(st.size())
		{
			if(st.top().x==1&&a.x==2)
			{
				st.pop();
				if(st.empty()) ans+=++num;//記錄並列的 
				else ans+=++st.top().sum;//記錄嵌套的 
			}
			else st.push(a);
		}
		else st.push(a);
	}
	printf("%d\n",ans);
	return 0;
}

T2:和數檢測(check)

簡化題目:

給定TT個詢問,nn個數,常數dd,求是否存在ai+aj=ma_i+a_j=mm<=1e9,n<=1e6(m<=1e9,n<=1e6)

題解:

(這個題,上去一看,n2n^2暴力跑啊,只有2020分,,那就開個桶跑,,只有4040,,,那就mapmap,只有505550—55分,那就二分,,也是5050,那就,,就分段單調指針跑二分,也就7070分,,,然而這個題我跑的mapmap,就拿了5050,,,但是還有的PHarr大佬竟然用pbdspbds直接就STLSTLO(n)O(n)的,,,tql)

正解:

分塊!!!

這題解也是真的妙,這是真的神奇,值域分塊,我真的是,,,服了,,還是序列分塊寫多了,值域分塊都忘的這麼幹淨了,這個題暴力來說就是開個桶啊,但是對於1e91e9進行分開真的是有意思,(這裏說明一下,其實真實的m不是1e91e9,在機房有位Tyouchie大佬寫的樹狀數組,寫的是1e71e7的,證明了所有數據在1e71e7之前就能找到答案,所以這個真實的數據並不是1e91e9)。

這就來解釋一下stdstd的標算,(由於solutionsolution真的是很不能看懂,覺得出題人是用文言寫的吧,所以就自己看代碼理解了一下,由於自己的分塊還是比較熟悉的就比較好看懂)

首先M=sqrt(m)40000M=sqrt(m) \approx40000 這就是塊長,然後這就是一個已經分過塊的桶,這其實就是叫值域分塊。

在每個塊裏面進行對這個數的存桶,然後怎麼優化1e91e9呢,就是把每個塊進行取模這樣的話,每個塊就是1400001—40000,然後對於每個數再進行取模等一下代碼細節,具體看代碼吧,應該很好理解。

代碼:

#include<bits/stdc++.h>
#define over(i,s,t) for(int i=s;i<=t;i++)
#define lver(i,t,s) for(int i=t;i>=s;i--)
using namespace std;
inline int read()
{
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();
	return s*w;
}
const int pool=1e6+7;
const int ocean=1e9;
const int sea=4e4;
vector<int>v[sea];
typedef vector<int>::iterator iter;
int T,n,m,flag,a[pool],block,f[sea*4];
int main()
{
//	freopen("check.in","r",stdin);
//	freopen("check.out","w",stdout);
	T=read();
	over(t,1,T)
	{
		n=read(); m=read();block=m/sea;
		over(i,0,block) v[i].clear(); int ans=0;
		over(i,1,n) 
		{
			int x=read(); int y=x%sea; x=x/sea;
			v[x].push_back(y);
		}
		over(i,0,block)
		{
            //先放進去a[i]
			int l=(m-(i+1)*sea+1)/sea,r=(m-i*sea)/sea,base=l*sea;
			over(j,l,r) for(iter it=v[j].begin();it!=v[j].end();it++) 
			f[*it+j*sea-base]=1;
			
            //對比
			for(iter it=v[i].begin();it!=v[i].end();it++) 
			if(f[m-*it-i*sea-base]) {ans=1;break;}
			
			//清空
            over(j,l,r) for(iter it=v[j].begin();it!=v[j].end();it++) 
			f[*it+j*sea-base]=0;
			if(ans) break; 
		}
		printf("%d\n",ans);
	}
	return 0;
}

T3:與(and)

簡化題目:

給你n個數,求你有多少種方法可以將它分成兩部分,使這兩部分至少有一個數,並且兩部分進行按位&操作後的結果是相同的。

題解:

(這個題我連指數級的暴力都打不出來,,,~~555555,還是之後又找到的大佬學了指數級的爆搜,由於指數級的爆搜不會,就直接想的正解,但是,正解又沒有完好的思路體系,所以就直接放棄了,,,)

這個題Lcentury以及他的同學,用DPDP成功AA掉,,Lec是寫了個80+80行+DPDP,然而他同學就更厲害了,,直接用STLSTL寫的DPDP,,就50行+,,,DPDP,,而我。。。還在想DPDP是怎麼AA掉的。。

正解:

容斥+並查集!!!

這個題啊,題解是真的妙!!!again(again)

首先這個題由於要求方案數,仔細看一下題,如果正這去做的話,就是一個DP的東西,去找到相同的,這樣子不會太好做,所以就用到了容斥,有所有的減去不相同的,由於你是要求有集合的一個和,也可以理解成並集,但是你可以求出每個集合,用容斥來做,這點可以參考一下下面的解釋,這樣的話答案就可以表示爲:
Ans=d=0131071(1)d×f(d) Ans=\sum_{d=0}^{131071}(-1)^d\times f(d)

f(d)=2k2(k) f(d)=2^k-2(k是並查集的個數)

這個其中的dd就是對於這個數限制,關於這個限制還是要好好說一下的,就是呢,你對於這個數的二進制位從最右邊開始進行遍歷,如果他是11或者他在這個限制內的數很符合這個限制的話,就記錄他的答案,這就需要我們先把這個限制的滿位遍歷出來,然後在對於每一個限制進行對於每一個數的遍歷,找到在這個限制內的所有的合法數,這一點可以用並查集進行合併,爲什麼用並查集進行合併呢,這裏呢,我可以舉個例子進行說明,當你已經限制了兩位的時候就是d=2d=2的時候,就可以有三種情況:01,10,1101,10,11,這樣的情況中可以知道,0101&10101010&01011111&01011111&1010 在這個限制中都是不相同的數,只有1111&1111 是對於這一限制有貢獻的,而由於現在要找到所有沒有貢獻的數,那就可以開個並查集對於像01011010這樣的數進行一個合併,用並查集來做就很好。這所有都做完,是把2172^{17}都做一遍,這樣的話最後就是查找一下並查集的個數就是kk,然後在減去你多加上的兩種不合法情況就是2k22^{k}-2 了,至於爲什麼是22kk次方,這個是組合數的基礎知識,不知道的也可以打表找出來。最後對答案加上容斥的部分再進行合併即可。

細說一下這個容斥:

設S是有窮集,P1,P2,P3,,PnP_1,P_2,P_3,…,Pn 是n條性質。S中的任一元素x對於這n條性質可能符合其中的1種,2種,3種……n種,也可能都不符合。設AiA_i 表示S種具有PiP_i 性質的元素構成的子集。有限集合A中的元素個數記爲A\left| A \right|。則:

S中具有性質P1,P2,P3,,PnP_1,P_2,P_3,…,Pn 的元素個數爲:
A1+A2++An \left|A_1\right|+\left|A_2\right|+…+\left|A_n\right|

=iAii<jAiAj+i<jAiAjAk+(1)n+1A1A2A3An =\sum_{i}\left|A_i\right|-\sum_{i<j}\left|A_i\cap A_j\right|+\sum_{i<j}\left|A_i\cap A_j\cap A_k \right|-…+(-1)^{n+1}\left|A_1\cap A_2\cap A_3…\cap A_n\right|
就是對於一大推要求和的集合,可以轉化爲求它們的交集,可以參考下下面的圖:

在這裏插入圖片描述

這樣的話就好理解多了,你需要求的就是所有藍色面積的和,但是你只知道A1,A2,A3AnA_1,A_2,A_3…A_n 這就可以通過一加一減的形式,減去重複的加上新增的,再加上之前的式子,這就很好理解了。

代碼:

指數級爆搜:

#include<bits/stdc++.h>
using namespace std;
const int nn=100;
int n, ans=0, a[nn];
bool vis[nn];
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}
void dfs(int now,int sum)//表示第now個數,選擇了sum個數 
{
	if(now==n+1)//由於數now的初值的 1,則最大就是n+1, 
	{
		if(sum==0||sum==n) return ;//如果兩個集合中存在沒有選擇的數 
		int x=(1<<18)-1, y=(1<<18)-1;//全賦爲 1 
		for(int i=1;i<=n;++i) if(vis[i]) x=x&a[i];else y=y&a[i];//判斷兩個集合內的答案是否是一樣的 
		if(x==y) ans++;
		return ;
	}
	dfs(now+1,sum); vis[now]=1;//不選擇這個數 
	dfs(now+1,sum+1); vis[now]=0;//選擇這個數
	return ;
}
int main()
{
//	freopen("and.in","r",stdin);
//	freopen("and.out","w",stdout);
	n=read(); for(int i=1;i<=n;++i) a[i]=read();
	dfs(1,0);
	printf("%d\n",ans);
	return 0;
}

正解:

#include<bits/stdc++.h>
#define int long long 
#define over(i,s,t) for(int i=s;i<=t;i++)
#define lver(i,t,s) for(int i=t;i>=s;i--)
using namespace std;
inline int read()
{
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();
	return s*w;
}
const int sea=61;
const int ocean=131072;
int n,ans=0,a[sea],b[sea],fa[sea];
int get(int x){return x==fa[x]?x:fa[x]=get(fa[x]);}
signed main()
{
//	freopen("and.in","r",stdin);
//  	freopen("and.out","w",stdout);
	n=read(); over(i,1,n) a[i]=read();
	b[0]=1; over(i,1,sea) b[i]=b[i-1]*2;
	over(d,0,ocean-1)
	{
		int d1=d,cnt=1,s;//容斥
		over(i,1,n) fa[i]=i; 
		for(int i=0;i<17;i++,(d1>>=1),s=i)//枚舉d的位數
		if(d1&1)
		{
			cnt=-cnt;//容斥 
			int j1=(int)b[i],j2=0,flag=0;//j1的初始值就是i滿位的時候 
			over(j,1,n) //枚舉所有的數 
			if(!(a[j]&j1))//如果這個數沒有超過滿位的j1
			{
				flag=1;//標記一下,如果是有的數大於現在的限制了,就直接擴大限制而不必是僅僅跳出次循環了 
		  		if(!j2) j2=get(j);//向上找到他的父親節點,就是在比他位數少的數中有1的 
				else fa[get(j)]=j2;//要是之前都沒有就把他直接賦成根節點,這樣就會得到好多並查集 
			}
			if(!flag) break;
		}
		if(s!=17) continue; 
		int num=0; over(i,1,n) if(i==get(i)) num++;  //記錄並查集個數 
		ans+=cnt*(b[num]-2);
		//答案就是所有位數上的(-1)^cnt*(2^k-2);具體的-2是因爲你在枚舉的時候並不能全部枚舉完,要刪除兩種情況,就是枚舉所有和枚舉0種的情況 
    }
	printf("%lld\n",ans);
 	return 0;
}

Day2總結:

恕我直言,今天的題解,真的是巧妙啊,值域分塊,並查集做序列操作,真的是強,而且特別考驗對普通序列的儘可能優化,頭腦風暴啊,tql,%%%%%%出題人。但是呢,我的T1是打掛了,,這就太慘了,儘管寫過原題,可能是對原題還不是特別透徹吧,需要再研究研究多寫幾遍,T2是太ex了,std在我本機上跑的5s+5s+,在大佬電腦刪跑的1s1s-,不知爲何,由於沒有給是時限,是看自己評測機上的時間,老師開了兩倍時限,我在可我還是死掉了,,,後來改了改才過,,但是這個想法是真的沒想到,桶還能這這樣開,,T3告訴我指數級(階乘級)暴力很重要,不要忽略,之前都是說說,但是沒寫過,還沒練過,然後就掛掉了。總之,今天是個頭腦風暴但暴力主場的不知怎麼說的比賽,所以還是那句話:一個問題要有兩種想法,一種保底暴力,一種天馬行空。

總結:

這兩天的模擬賽打下來是150,要是D2T1不打掛就250了,然後就是在打指數級暴力就是270了,大概就接近省一了,,但是說實話,兩天大概都能拿個150—180左右纔可以穩穩的啊,這就很難了我還是菜,儘管就差不到60天了,我還是要好好努力的!!!

Continue……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章