【长沙集训】2017.10.10
?
Adore
1.1 問題描述
小 w 偶然間遇到了一個(gè) DAG。 這個(gè) DAG 有 m 層,第一層只有1個(gè)源點(diǎn),最后一層只有1個(gè)匯點(diǎn),剩下的每一層都有 k 個(gè) 節(jié)點(diǎn)。
現(xiàn)在小 w 每次可以取反第 i(1 < i < n ? 1) 層和第 i + 1 層之間的連邊。也就是把原本從 (i, k1) 連到 (i + 1, k2) 的邊,變成從
(i, k2) 連到 (i + 1, k1)。 請(qǐng)問他有多少種取反的方案,把從源點(diǎn)到匯點(diǎn)的路徑數(shù)變成偶數(shù)條? 答案對(duì) 998244353 取模。
1.2?輸入格式
第一行兩個(gè)整數(shù) m, k。
接下來 m ? 1 行, 第一行和最后一行有 k 個(gè)整數(shù) 0 或 1,剩下每行有 k 2 個(gè)整數(shù) 0 或 1,
第 (j ? 1) × k + t 個(gè)整數(shù)表示 (i, j) 到 (i + 1, t) 有沒有邊。
1.3 輸出格式
一行一個(gè)整數(shù)表示答案。
1.4 樣例輸入
5 3
1 0 1
0 1 0 1 1 0?0 0 1
0 1 1?1 0 0 0 1 1
0 1 1
1.5樣例輸出
4
1.6數(shù)據(jù)規(guī)模與約定
20% 的數(shù)據(jù)滿足 n ≤ 10, k ≤ 2
40% 的數(shù)據(jù)滿足 n ≤ 10^3 , k ≤ 2。
60% 的數(shù)據(jù)滿足 m ≤ 10^3 , k ≤ 5。
100% 的數(shù)據(jù)滿足 4 ≤ m ≤ 10^4 , k ≤ 10。
?1.
這要是Noip d1t1我也不用學(xué)oi了。。。
每一層只有10個(gè)點(diǎn),我們只關(guān)心每個(gè)點(diǎn)的奇偶情況,于是可以考慮狀壓dp。dp[i][j]表示第i層奇偶情況為j的答案。
暴力的寫法,枚舉每一層,每種情況,枚舉每條邊暴力地更新奇偶算轉(zhuǎn)移到的狀態(tài)。60分。場(chǎng)上zz不知道哪個(gè)地方莫名多了一個(gè)忘刪掉的for循環(huán),炸了兩個(gè)點(diǎn)。。
優(yōu)化一下,預(yù)處理出連向每個(gè)點(diǎn)的邊的集合,用一個(gè)二進(jìn)制串表示,然后每次和轉(zhuǎn)移來的狀態(tài)取交,判斷這個(gè)數(shù)的1的個(gè)數(shù)的奇偶(這一步同樣是預(yù)處理)。
然后又是垃圾卡常,,可能我真的是傳說中的 真·大常數(shù)選手吧。。好不容易卡進(jìn)去。。
//Twenty #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<stack> typedef long long LL; const LL mod=998244353; const int maxn=1e4+299; const int maxm=1e6+299; int m,k,x,s,t; using namespace std; int a[maxn][11],b[maxn][11],ok[maxn]; int f[10005][1030];inline int get(int &x) {int ret=0; char ch=getchar();while(ch<'0'||ch>'9') ch=getchar();for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';x=ret; }void work() {int nn=(1<<k)-1;for(register int i=0;i<=nn;i++) ok[i]=ok[i>>1]^(i&1);for(register int i=3;i<=m;i++) {for(register int j=0;j<=nn;j++) if(f[i-1][j]){int now=0,s1=0,s2=0;for(register int l=1;l<=k;l++) {s1|=ok[a[i][l]&j]<<l-1;s2|=ok[b[i][l]&j]<<l-1;}f[i][s1]+=f[i-1][j];if(f[i][s1]>=mod) f[i][s1]-=mod;if(i!=m) {f[i][s2]+=f[i-1][j];if(f[i][s2]>=mod) f[i][s2]-=mod;}}} }int main() {freopen("adore.in","r",stdin);freopen("adore.out","w",stdout);get(m); get(k);int now=0;for(register int i=1;i<=k;i++) {get(x);if(!x) continue;now|=(1<<i-1);}f[2][now]=1;for(register int i=2;i<m-1;i++) {for(register int j=1;j<=k;j++)for(register int l=1;l<=k;l++) {get(x);if(!x) continue;a[i+1][l]|=(1<<j-1);b[i+1][j]|=(1<<l-1);}}for(register int i=1;i<=k;i++) {get(x);if(!x) continue;a[m][1]|=(1<<i-1);}work();printf("%d\n",f[m][0]);fclose(stdin);fclose(stdout);return 0; } View Code?
?
Confess
2.1 問題描述
小w 隱藏的心緒已經(jīng)難以再隱藏下去了。 小w 有 n + 1(保證 n 為偶數(shù)) 個(gè)心緒,每個(gè)都包含了 [1, 2n] 的一個(gè)子集。 現(xiàn)在他要找到隱藏的任意兩個(gè)心緒,使得他們的交大于等于 n/ 2。
2.2 輸入格式
一行一個(gè)整數(shù) n。
接下來每行一個(gè)長(zhǎng)度為 k 的字符串,該字符串是一個(gè) 64 進(jìn)制表示,
ASCII 碼為 x 的字符代 表著 x ? 33,所有字符在 33 到 33 + 63 之間。
轉(zhuǎn)為二進(jìn)制表示有 6k 位,它的前 2n 個(gè)字符就是讀入的集合,
第 i 位為 1 表示這個(gè)集合包 含 i,為 0 表示不包含。
2.3 輸出格式
一行兩個(gè)不同的整數(shù)表示兩個(gè)集合的編號(hào)。
如果無解輸出”NO Solution”。
2.4 樣例輸入
10
EVK#
IH=#
676"
R7,#
74S"
6V2#
O3J#
S-7$
NU5"
C[$$
3N.#
2.5 樣例輸出
1 2
2.6 數(shù)據(jù)規(guī)模與約定
對(duì)于 20% 的數(shù)據(jù)滿足 n ≤ 100。
對(duì)于 50% 的數(shù)據(jù)滿足 n ≤ 1 × 10^3。
對(duì)于 100% 的數(shù)據(jù)滿足 n ≤ 6 × 10^3。
?2.
t1寫得太難受+語(yǔ)文太爛,沒讀懂題,暴力都沒打直接輸出no solution。
然而沒有No solution的情況,正解就是暴力。
首先”NO Solution” 兩個(gè)單詞大小寫不一致,所以肯定是亂 打的,不會(huì)有無解。
證明?我們不妨算一算如果隨機(jī)選兩個(gè)集合,他們交的期望
min( ∑2n i=1 C(ci ,2) C(n+1,2) | ∑2n i=1 ci = n(n + 1)) = n?1/2
注意 n 是偶數(shù),所以大于 n?2/2 即可說明會(huì)有交為 n 的
由于大了一個(gè)常數(shù),所以至少有 n 對(duì)!
隨機(jī) O(n) 對(duì)即可
標(biāo)解用了bitset,開O2跑得賊快,不用bitset就又是垃圾卡常,怎么卡都卡不進(jìn),只能一邊輸一遍做找到答案就輸都不輸了才ok。。。
//Twenty #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<cmath> #include<ctime> #include<queue> using namespace std; const int maxn=6e3+5; int n,sz,b[maxn]; char ch[60005]; bool a[maxn][2*maxn],tp[10]; int ok(int x,int y) {int ret=0;for(int i=1;i<=2*n;i++) {if(a[x][i]==1&&a[y][i]==1) ret++;if(ret>=n/2) return 1;}return ret>=n/2; } int main() {freopen("confess.in","r",stdin);freopen("confess.out","w",stdout);scanf("%d",&n);for(register int i=1;i<=n+1;i++) {cin>>ch;int p=0,q=0;while(q<=2*n){int mid=ch[p++]-33;for(int j=0;j<6;j++)a[i][++q]=mid&(1<<j);} for(register int j=i-1;j>=1;j--) if(ok(i,j)) {printf("%d %d\n",i,j);return 0;}}fclose(stdin);fclose(stdout);return 0; } View Code--------------------------------------------------------------------------------------------
事實(shí)證明被卡常是某個(gè)叫random_shuffle()的函數(shù)的鍋。換成sort就過了。
還有g(shù)etchar會(huì)比cin快很多。常數(shù)這種東西太可怕了。
//Twenty #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<cmath> #include<ctime> #include<queue> using namespace std; const int maxn=6e3+5; int n,sz,b[maxn],c[maxn]; char s[105]; bool a[maxn][2*maxn],tp[10]; int ok(int x,int y) {int ret=0;for(int i=1;i<=2*n;i++) {if(a[x][i]==1&&a[y][i]==1) ret++;if(ret>=n/2) return 1;}return ret>=n/2; }bool cmp(const int &x,const int &y) {return b[x]<b[y]; }int main() {freopen("confess.in","r",stdin);freopen("confess.out","w",stdout);srand(time(0));cin>>n;for(int i=1;i<=n+1;i++) {int tot=0; char c=getchar();while(c<33||c>96)c=getchar();while(c>=33&&c<=96) {for(int j=0;j<=5&&tot<=2*n;j++)a[i][++tot]=(((c-33)>>j)&1);c=getchar();}}for(int i=1;i<=n+1;i++) c[i]=i,b[i]=rand();sort(c+1,c+n+2,cmp);for(int i=1;i<=n+1;i++) {for(int j=i+1;j<=n+1;j++)if(ok(c[i],c[i+1])) {printf("%d %d\n",c[i],c[i+1]);return 0;}}fclose(stdin);fclose(stdout);return 0; } View Code?
?
?Repulsed
3.1 問題描述
小 w 心理的火焰就要被熄滅了。 簡(jiǎn)便起見,假設(shè)小w 的內(nèi)心是一棵 n ? 1 條邊,n 個(gè)節(jié)點(diǎn)的樹。 現(xiàn)在你要在每個(gè)節(jié)點(diǎn)里放一些滅火器,每個(gè)節(jié)點(diǎn)可以放任意多個(gè)。 接下來每個(gè)節(jié)點(diǎn)都要被分配給一個(gè)最多 k 條邊遠(yuǎn)的滅火器,每個(gè)滅火器最多能分配給 s 個(gè)節(jié) 點(diǎn)。 最少要多少個(gè)滅火器才能讓小 w 徹底死心呢?
3.2 輸入格式
第一行三個(gè)整數(shù) n, s, k。
接下來 n ? 1 行每行兩個(gè)整數(shù)表示一條邊。
3.3 輸出格式
一行一個(gè)整數(shù)表示答案
3.4 樣例輸入
10 10 3
1 8
2 3
1 5
2 4
1 2
8 9
8 10
5 6
5 7
3.5?樣例輸出
1
3.6 數(shù)據(jù)規(guī)模與約定
對(duì)于 20% 的數(shù)據(jù)滿足 n ≤ 100, k ≤ 2。
對(duì)于另外 20% 的數(shù)據(jù)滿足 k = 1。
對(duì)于另外 20% 的數(shù)據(jù)滿足 s = 1。
對(duì)于 100% 的數(shù)據(jù)滿足 n ≤ 10^5 , k ≤ 20, s ≤ 10
?至底往上貪心。
考慮一條鏈上去只要能管得到肯定往上放比較優(yōu),每次從下到上再在上面考慮下面的情況。
g[x][i]表示x點(diǎn)往下i的距離的位置還需要多少滅火器,f[x][i]表示x點(diǎn)往下i的距離的位置有多少?zèng)]用的滅火器。
若g[x][k]還不為0,則在該點(diǎn)放滅火器。
考慮子樹中長(zhǎng)度為k的距離的位置和k-1距離的位置的互相配放。
到根節(jié)點(diǎn)后再把沒用的全用了,還差的一起補(bǔ)上。
//Twenty #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<cmath> #include<ctime> #include<queue> const int maxn=1e5+299; int n,s,k; using namespace std;int ans,ecnt,fir[maxn],nxt[maxn*2],to[maxn*2]; void add(int u,int v) {nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; }int f[maxn][22],g[maxn][22]; void dfs(int x,int fa) {for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa){int v=to[i]; dfs(v,x);for(int j=1;j<=k;j++) {f[x][j]=min(n,f[x][j]+f[v][j-1]);g[x][j]+=g[v][j-1];} }g[x][0]++;if(g[x][k]) {int tp=(g[x][k]-1)/s+1;f[x][0]=tp*s,ans+=tp;}for(int i=0;i<=k;i++) {int j=k-i;int d=min(f[x][i],g[x][j]);f[x][i]-=d; g[x][j]-=d;}for(int i=0;i<k;i++) {int j=k-i-1;int d=min(f[x][i],g[x][j]);f[x][i]-=d; g[x][j]-=d;} }int main() {freopen("repulsed.in","r",stdin);freopen("repulsed.out","w",stdout);scanf("%d%d%d",&n,&s,&k);for(int i=1;i<n;i++) {int x,y;scanf("%d%d",&x,&y);add(x,y);}dfs(1,0);for(int i=0;i<=k;i++)for(int j=0;j<=k;j++) {if(i+j<=k) {int d=min(f[1][i],g[1][j]);f[1][i]-=d; g[1][j]-=d;}}int tot=0;for(int i=0;i<=k;i++) {if(g[1][i]) tot+=g[1][i];}ans+=(tot?(tot-1)/s+1:0);printf("%d\n",ans);fclose(stdin);fclose(stdout);return 0; } View Code?
轉(zhuǎn)載于:https://www.cnblogs.com/Achenchen/p/7647431.html
總結(jié)
以上是生活随笔為你收集整理的【长沙集训】2017.10.10的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神经网络求解NS方程
- 下一篇: 软件技术专业-就业提示(一、实施工程师)