又是隻\(A\)了四題...\(\rm E,F\)都很水可是開\(\rm vp\)的時候腦子抽掉了一直在想\(\rm F\)的\(\rm fwt\)作法就沒時間了....c++
比賽連接:https://codeforc.es/contest/959git
題目連接就不放了 纔不是由於懶算法
一步的博弈題...奇偶判斷題。spa
#include<bits/stdc++.h> using namespace std; #define int long long void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } #define ll long long void print(ll x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(ll x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int > #define vec vector<int > #define pb push_back #define mp make_pair #define fr first #define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 2e5+10; const int inf = 1e9; const lf eps = 1e-8; ll ans,s; int n,a[maxn]; signed main() { read(n); if(n&1) puts("Ehab"); else puts("Mahmoud"); return 0; }
並查集+哈希,考知識點的普及組題。code
#include<bits/stdc++.h> using namespace std; #define int long long void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } #define ll long long void print(ll x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(ll x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int > #define vec vector<int > #define pb push_back #define mp make_pair #define fr first #define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 2e5+10; const int inf = 1e9; const lf eps = 1e-8; #define ull unsigned ll char s[maxn]; int n,a[maxn],tot,fa[maxn],val[maxn],k,m,ans; int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);} map<ull,int > h; signed main() { read(n),read(k),read(m); for(int i=1;i<=n;i++) { scanf("%s",s+1);int x=strlen(s+1);ull r=0; for(int j=1;j<=x;j++) r=r*31+s[j]; h[r]=++tot; } for(int i=1;i<=n;i++) read(val[i]),fa[i]=i; for(int i=1;i<=k;i++) { int r,x,y;read(r);read(x); for(int j=2;j<=r;j++) { read(y);int u=find(y),v=find(x); if(u!=v) fa[u]=v,val[v]=min(val[v],val[u]); val[v]=min(val[v],val[y]); } } for(int i=1;i<=m;i++) { scanf("%s",s+1);int x=strlen(s+1);ull r=0; for(int j=1;j<=x;j++) r=r*31+s[j]; ans+=val[find(h[r])]; }write(ans); return 0; }
簡單的構造題,錯誤就是兩個菊花圖連起來,正確的就是一個菊花圖。get
錯誤的\(n\leqslant 5\)時無解。it
具體來講錯誤的狀況就是以\(1\)爲根和以\(2\)爲根分別構造菊花圖,而後鏈接\((1,2)\),正確答案爲\(2\)可是他的算法會獲得兩個菊花圖點數的最小值。圖我就懶得畫了io
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } #define ll long long void print(ll x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(ll x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int > #define vec vector<int > #define pb push_back #define mp make_pair #define fr first #define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 2e5+10; const int inf = 1e9; const lf eps = 1e-8; #define ull unsigned ll int n,tot; signed main() { read(n); if(n<=5) puts("-1"); else { int x=((n-1)>>1)+!(n&1);tot=1; for(int i=1;i<=x;i++) printf("1 %d\n",++tot); for(int i=x+1;i<n;i++) printf("2 %d\n",++tot); } for(int i=2;i<=n;i++) printf("1 %d\n",i); return 0; }
有點意思的貪心題。class
答案顯然是要儘量的貼着給出的數列,那麼咱們先暴力的找到第一個和前面不互質的數,記起來,這一步能夠分解質因數,\(O(n\log n)\)。test
而後咱們暴力的把這個數不停的\(+1\)直到和前面的互質,這一步由於至多加到前面沒出現的最小的質數,因此也是\(O(n\log n)\)的,到這一步均可以保證正確性。
後面咱們貪心的從小到大選擇沒出現過的質數,這樣必定最優,由於若是你選一個合數,那麼顯然是沒有把它拆成若干個質數仍前面優。
總複雜度\(O(n\log n)\)。
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } #define ll long long void print(ll x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(ll x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int > #define vec vector<int > #define pb push_back #define mp make_pair #define fr first #define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 2e5+10; const int inf = 1e9; const lf eps = 1e-8; const int N = 4e6; #define ull unsigned ll int n,a[maxn],vis[N+10],pri[N+10],use[N+10],mn[N+10],tot,cnt; void sieve() { for(int i=2;i<=N;i++) { if(!vis[i]) pri[++tot]=i,mn[i]=i; for(int j=1;j<=tot&&i*pri[j]<=N;j++) { mn[i*pri[j]]=pri[j]; vis[i*pri[j]]=1; if(i%pri[j]==0) break; } } } int check(int x,int t) { while(x!=1) { if(t) use[mn[x]]=1; else if(use[mn[x]]) return 0; x/=mn[x]; }return 1; } signed main() { read(n);for(int i=1;i<=n;i++) read(a[i]); sieve();int bo=0;cnt=1; for(int i=1;i<=n;i++) { if(bo) { while(use[pri[cnt]]) { cnt++; } a[i]=pri[cnt];cnt++; } else if(check(a[i],0)) check(a[i],1); else { for(int k=a[i]+1;;k++) if(check(k,0)) {check(k,1),a[i]=k,bo=1;break;} } } for(int i=1;i<=n;i++) printf("%d ",a[i]);puts(""); return 0; }
這是本場最有意思的題了...
考慮手玩\(\rm kruskal\)的過程,能夠發現每次都只有\(2\)的冪會形成貢獻。
具體的來講,第一次\(2^0=1\)會形成貢獻,會把\(n\)個點兩兩分紅若干個連通塊,分別是\((0,1),(2,3)\cdots\),那麼咱們能夠把這\(n\)個點當作\(\lceil\frac{n}{2}\rceil\)個點。
第二次\(2^1=2\)會把這\(\lceil\frac{n}{2}\rceil\)個點又兩兩分組,連邊方式爲\((0,2),(4,6),(8,10)\cdots\)。
那麼代碼只要模擬這個過程就行了,複雜度\(O(\log n)\)。
順便說一下這個數列在\(\rm OEIS\)上有:http://oeis.org/A006520
#include<bits/stdc++.h> using namespace std; #define int long long void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } void print(int x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define ll long long #define pii pair<int,int > #define vec vector<int > #define pb push_back #define mp make_pair #define fr first #define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 2e5+10; const int inf = 1e9; const lf eps = 1e-8; const int mod = 1e9+7; int n,ans; signed main() { read(n); for(int i=1;i<n;i<<=1) ans+=i*((n/i+(n%i!=0))>>1); write(ans); return 0; }
我竟然沒想到線性基.......多是過久沒用過了把。
離線以後前綴線性基就行了,假設咱們當前處理到\([1,p]\),如今的數爲\(x\)。
那麼若是線性基不能表示\(x\)顯然無解,不然注意到線性基能夠表示\([1,p]\)的每個數,那麼線性基也必定能夠表示除了線性基以外全部數列中的數任意選若干個以後異或\(x\)的結果。
那麼答案就是線性基以外的數任意選的方案數,也就是\(2^{p-sz}\),其中\(sz\)爲線性基的大小。
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } void print(int x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define ll long long #define pii pair<int,int > #define vec vector<int > #define pb push_back #define mp make_pair #define fr first #define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 2e5+10; const int inf = 1e9; const lf eps = 1e-8; const int mod = 1e9+7; int n,T,a[maxn],sz,r[30],pw[maxn]; struct Q {int p,x,id,ans;}q[maxn]; int cmp1(Q a,Q b) {return a.p<b.p;} int cmp2(Q a,Q b) {return a.id<b.id;} void ins(int x) { for(int i=20;~i;i--) { if(!(x&(1<<i))) continue; if(r[i]) x^=r[i]; else return sz++,r[i]=x,void(); } } int query(int x) { for(int i=20;~i;i--) { if(!(x&(1<<i))) continue; if(r[i]) x^=r[i]; else return 0; }return 1; } int main() { read(n),read(T);FOR(i,1,n) read(a[i]); FOR(i,1,T) read(q[i].p),read(q[i].x),q[i].id=i; int t=1;pw[0]=1;sort(q+1,q+T+1,cmp1); for(int i=1;i<=n;i++) { ins(a[i]);pw[i]=pw[i-1]*2%mod; while(q[t].p==i) { if(query(q[t].x)) q[t].ans=pw[i-sz]; else q[t].ans=0;t++; } }sort(q+1,q+T+1,cmp2); FOR(i,1,T) write(q[i].ans); return 0; }