日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【长沙集训】2017.10.10

發布時間:2023/12/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【长沙集训】2017.10.10 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

Adore

1.1 問題描述

小 w 偶然間遇到了一個 DAG。 這個 DAG 有 m 層,第一層只有1個源點,最后一層只有1個匯點,剩下的每一層都有 k 個 節點。

現在小 w 每次可以取反第 i(1 < i < n ? 1) 層和第 i + 1 層之間的連邊。也就是把原本從 (i, k1) 連到 (i + 1, k2) 的邊,變成從

(i, k2) 連到 (i + 1, k1)。 請問他有多少種取反的方案,把從源點到匯點的路徑數變成偶數條? 答案對 998244353 取模。

1.2?輸入格式

第一行兩個整數 m, k。

接下來 m ? 1 行, 第一行和最后一行有 k 個整數 0 或 1,剩下每行有 k 2 個整數 0 或 1,

第 (j ? 1) × k + t 個整數表示 (i, j) 到 (i + 1, t) 有沒有邊。

1.3 輸出格式

一行一個整數表示答案。

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數據規模與約定

20% 的數據滿足 n ≤ 10, k ≤ 2

40% 的數據滿足 n ≤ 10^3 , k ≤ 2。

60% 的數據滿足 m ≤ 10^3 , k ≤ 5。

100% 的數據滿足 4 ≤ m ≤ 10^4 , k ≤ 10。

?1.

這要是Noip d1t1我也不用學oi了。。。

每一層只有10個點,我們只關心每個點的奇偶情況,于是可以考慮狀壓dp。dp[i][j]表示第i層奇偶情況為j的答案。

暴力的寫法,枚舉每一層,每種情況,枚舉每條邊暴力地更新奇偶算轉移到的狀態。60分。場上zz不知道哪個地方莫名多了一個忘刪掉的for循環,炸了兩個點。。

優化一下,預處理出連向每個點的邊的集合,用一個二進制串表示,然后每次和轉移來的狀態取交,判斷這個數的1的個數的奇偶(這一步同樣是預處理)。

然后又是垃圾卡常,,可能我真的是傳說中的 真·大常數選手吧。。好不容易卡進去。。

//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 隱藏的心緒已經難以再隱藏下去了。 小w 有 n + 1(保證 n 為偶數) 個心緒,每個都包含了 [1, 2n] 的一個子集。 現在他要找到隱藏的任意兩個心緒,使得他們的交大于等于 n/ 2。

2.2 輸入格式

一行一個整數 n。

接下來每行一個長度為 k 的字符串,該字符串是一個 64 進制表示,

ASCII 碼為 x 的字符代 表著 x ? 33,所有字符在 33 到 33 + 63 之間。

轉為二進制表示有 6k 位,它的前 2n 個字符就是讀入的集合,

第 i 位為 1 表示這個集合包 含 i,為 0 表示不包含。

2.3 輸出格式

一行兩個不同的整數表示兩個集合的編號。

如果無解輸出”NO Solution”。

2.4 樣例輸入

10

EVK#

IH=#

676"

R7,#

74S"

6V2#

O3J#

S-7$

NU5"

C[$$

3N.#

2.5 樣例輸出

1 2

2.6 數據規模與約定

對于 20% 的數據滿足 n ≤ 100。

對于 50% 的數據滿足 n ≤ 1 × 10^3。

對于 100% 的數據滿足 n ≤ 6 × 10^3。

?2.

t1寫得太難受+語文太爛,沒讀懂題,暴力都沒打直接輸出no solution。

然而沒有No solution的情況,正解就是暴力。

首先”NO Solution” 兩個單詞大小寫不一致,所以肯定是亂 打的,不會有無解。

證明?我們不妨算一算如果隨機選兩個集合,他們交的期望

min( ∑2n i=1 C(ci ,2) C(n+1,2) | ∑2n i=1 ci = n(n + 1)) = n?1/2

注意 n 是偶數,所以大于 n?2/2 即可說明會有交為 n 的

由于大了一個常數,所以至少有 n 對!

隨機 O(n) 對即可

標解用了bitset,開O2跑得賊快,不用bitset就又是垃圾卡常,怎么卡都卡不進,只能一邊輸一遍做找到答案就輸都不輸了才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

--------------------------------------------------------------------------------------------

事實證明被卡常是某個叫random_shuffle()的函數的鍋。換成sort就過了。

還有getchar會比cin快很多。常數這種東西太可怕了。

//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 心理的火焰就要被熄滅了。 簡便起見,假設小w 的內心是一棵 n ? 1 條邊,n 個節點的樹。 現在你要在每個節點里放一些滅火器,每個節點可以放任意多個。 接下來每個節點都要被分配給一個最多 k 條邊遠的滅火器,每個滅火器最多能分配給 s 個節 點。 最少要多少個滅火器才能讓小 w 徹底死心呢?

3.2 輸入格式

第一行三個整數 n, s, k。

接下來 n ? 1 行每行兩個整數表示一條邊。

3.3 輸出格式

一行一個整數表示答案

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 數據規模與約定

對于 20% 的數據滿足 n ≤ 100, k ≤ 2。

對于另外 20% 的數據滿足 k = 1。

對于另外 20% 的數據滿足 s = 1。

對于 100% 的數據滿足 n ≤ 10^5 , k ≤ 20, s ≤ 10

?至底往上貪心。

考慮一條鏈上去只要能管得到肯定往上放比較優,每次從下到上再在上面考慮下面的情況。

g[x][i]表示x點往下i的距離的位置還需要多少滅火器,f[x][i]表示x點往下i的距離的位置有多少沒用的滅火器。

若g[x][k]還不為0,則在該點放滅火器。

考慮子樹中長度為k的距離的位置和k-1距離的位置的互相配放。

到根節點后再把沒用的全用了,還差的一起補上。

//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

?

轉載于:https://www.cnblogs.com/Achenchen/p/7647431.html

總結

以上是生活随笔為你收集整理的【长沙集训】2017.10.10的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。