4.14 網絡流專項測試html
先看T1,不會,看T2,仙人掌???wtf??棄療。看T3,貌似最可作了,而後開始剛,剛了30min無果,打了50分暴力,而後接着去看T1,把序列差分了一下,推了會式子,發現是傻逼費用流,而後碼碼碼,碼完秒過大樣例,以爲比較穩,又肉眼查了會錯,就放了。而後接着推T3,發現我會作一個限制條件的,貌似和T1差很少,而後就寫了,感受能多騙點分,以後看了看T2,發現30裸樹剖,30裸最大流,而後碼碼碼。最後查了會錯,發現T1沒開long long,趕忙改了。100+44+63=207 rank1/5。T2掛了12分,不知道爲何,真的是靜態仙人掌裸題,T3比較巧妙。ios
T1,差分以後每一個原本就知足條件的位置有一個能夠貢獻的流量從S連過來,不知足條件的位置有一個須要的流量連向T。而後每種操做能夠鏈接兩個距離爲l的位置,而後直接最小費用最大流便可,判斷無解能夠看最大流是否是等於咱們須要的流量。c++
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #define inf 0x3fffffff 8 #define N 250 9 using namespace std; 10 int e=2,head[N]; 11 struct edge{ 12 int u,v,f,w,next; 13 }ed[N*N<<1]; 14 void add(int u,int v,int f,int w){ 15 ed[e].u=u;ed[e].v=v;ed[e].f=f;ed[e].w=w; 16 ed[e].next=head[u];head[u]=e++; 17 ed[e].u=v;ed[e].v=u;ed[e].f=0;ed[e].w=-w; 18 ed[e].next=head[v];head[v]=e++; 19 } 20 int dis[N],pre[N],bo[N],tim,S,T; 21 int sum,n,m,a[N],b[N]; 22 bool spfa(){ 23 memset(dis,0x3f,sizeof dis); 24 tim++; 25 deque<int> q;q.push_front(S);dis[S]=0; 26 while(!q.empty()){ 27 int x=q.front();q.pop_front();bo[x]=0; 28 for(int i=head[x];i;i=ed[i].next){ 29 int v=ed[i].v; 30 if(ed[i].f&&dis[v]>dis[x]+ed[i].w){ 31 dis[v]=dis[x]+ed[i].w;pre[v]=i; 32 if(bo[v]!=tim){ 33 bo[v]=tim; 34 if(!q.empty()&&dis[v]<dis[q.front()])q.push_front(v); 35 else q.push_back(v); 36 } 37 } 38 } 39 } 40 return dis[T]!=dis[T+1]; 41 } 42 long long ans=0; 43 int dfs(int x,int f){ 44 bo[x]=tim; 45 int now=0; 46 if(x==T){ 47 ans+=1ll*f*dis[T]; 48 return f; 49 } 50 for(int i=head[x];i;i=ed[i].next){ 51 if(ed[i].f&&dis[ed[i].v]==dis[x]+ed[i].w&&bo[ed[i].v]!=tim){ 52 int nxt=dfs(ed[i].v,min(f,ed[i].f)); 53 now+=nxt;f-=nxt;ed[i].f-=nxt;ed[i^1].f+=nxt; 54 if(!f)break; 55 } 56 } 57 return now; 58 } 59 void work(){ 60 int flow=0; 61 while(spfa()){ 62 do{ 63 tim++; 64 flow+=dfs(S,inf); 65 }while(bo[T]==tim); 66 } 67 if(flow!=sum)puts("-1"); 68 else printf("%lld\n",ans); 69 } 70 int main(){ 71 // freopen("test.in","r",stdin); 72 scanf("%d%d",&n,&m); 73 S=n+1;T=S+1; 74 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 75 for(int i=1;i<n;i++){ 76 b[i]=a[i+1]-a[i]; 77 if(b[i]>0)add(S,i,b[i],0); 78 else add(i,T,-b[i],0),sum-=b[i]; 79 } 80 add(S,0,inf,0);add(S,n,inf,0); 81 char o[5]; 82 for(int i=1,l,c;i<=m;i++){ 83 scanf("%s%d%d",o,&l,&c); 84 for(int j=0;j+l<=n;j++){ 85 if(o[0]=='+')add(j+l,j,inf,c); 86 else add(j,j+l,inf,c); 87 } 88 } 89 work(); 90 return 0; 91 }
T2,靜態仙人掌裸題,咕咕咕。算法
T3,比較巧妙的一個費用流。咱們先假設將全部的零件都放進去,這樣可能會出現不合法的狀況,咱們仍是考慮枚舉,這裏咱們枚舉每行/列的限制,而後咱們將對應行和列之間連上(k,0)的邊,表明最多有這麼多不被刪去,剩下的若是位置(i,j)是合法的,則從i行想j列連一條(1,1)的邊,表明這個零件被刪去了。而後每次咱們跑的都是最小費用最大流,只須要判斷是否滿流以及最後的零件總數是否是知足條件。數組
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <deque> 5 #define N 88 6 #define inf 0x3fffffff 7 using namespace std; 8 int e,head[N]; 9 struct edge{ 10 int u,v,f,w,next; 11 }ed[N*N]; 12 void add(int u,int v,int f,int w){ 13 ed[e].u=u;ed[e].v=v;ed[e].f=f;ed[e].w=w; 14 ed[e].next=head[u];head[u]=e++; 15 ed[e].u=v;ed[e].v=u;ed[e].f=0;ed[e].w=-w; 16 ed[e].next=head[v];head[v]=e++; 17 } 18 char s[N][N]; 19 int n,A,B,S,T,ans=-1; 20 int dis[N],pre[N],bo[N]; 21 int a[N],b[N],tot,lim,num1; 22 bool spfa(){ 23 memset(dis,0x3f,sizeof dis); 24 memset(bo,0,sizeof bo); 25 deque<int> q;q.push_front(S);dis[S]=0; 26 while(!q.empty()){ 27 int x=q.front();q.pop_front();bo[x]=0; 28 for(int i=head[x];i;i=ed[i].next){ 29 int v=ed[i].v; 30 if(ed[i].f&&dis[v]>dis[x]+ed[i].w){ 31 dis[v]=dis[x]+ed[i].w;pre[v]=i; 32 if(!bo[v]){ 33 bo[v]=1; 34 if(!q.empty()&&dis[v]<dis[q.front()])q.push_front(v); 35 else q.push_back(v); 36 } 37 } 38 } 39 } 40 return dis[T]!=dis[T+1]; 41 } 42 int Flow,Cost; 43 int dfs(int x,int f){ 44 bo[x]=1; 45 if(x==T){ 46 Flow+=f; 47 Cost+=dis[T]*f; 48 return f; 49 } 50 int ans=0; 51 for(int i=head[x];i;i=ed[i].next){ 52 int v=ed[i].v; 53 if(ed[i].f&&dis[v]==dis[x]+ed[i].w&&!bo[v]){ 54 int nxt=dfs(v,min(f,ed[i].f)); 55 ans+=nxt;f-=nxt;ed[i].f-=nxt;ed[i^1].f+=nxt; 56 if(!f)break; 57 } 58 } 59 return ans; 60 } 61 void work(){ 62 Flow=0,Cost=0; 63 while(spfa()){ 64 do{ 65 memset(bo,0,sizeof bo); 66 dfs(S,inf); 67 }while(bo[T]); 68 } 69 if(Flow==tot&&lim*B<=(tot-Cost)*A) 70 ans=max(ans,tot-Cost); 71 } 72 int tim; 73 int main(){ 74 while(scanf("%d%d%d",&n,&A,&B)==3&&((n+A+B)!=0)){ 75 num1=0;tot=0; 76 memset(a,0,sizeof a); 77 memset(b,0,sizeof b); 78 for(int i=1;i<=n;i++){ 79 scanf("%s",s[i]+1); 80 for(int j=1;j<=n;j++){ 81 if(s[i][j]!='/'){ 82 tot++;a[i]++;b[j]++; 83 if(s[i][j]=='C')num1++; 84 } 85 } 86 } 87 S=n*2+1;T=S+1;ans=-1; 88 for(lim=0;lim<=n;lim++){ 89 e=2;memset(head,0,sizeof head); 90 for(int i=1;i<=n;i++){ 91 add(S,i,a[i],0); 92 add(n+i,T,b[i],0); 93 add(i,n+i,lim,0); 94 for(int j=1;j<=n;j++)if(s[i][j]=='.') 95 add(i,n+j,1,1); 96 } 97 work(); 98 } 99 printf("Case %d: ",++tim); 100 if(ans==-1)puts("impossible"); 101 else printf("%d\n",ans-num1); 102 } 103 return 0; 104 }
裸的spfa在bzoj上T,在wangxh的建議下改爲了多路增廣,而後跑的飛快!安全
4.17網絡
開場看T1,貌似不是很難,可是yy了一會,感受O(n^2)暴力有點難寫,因而去看T2,發現是二分圖博弈裸題,而後碼,二分圖和dinic拍,原本覺得二分圖過不了呢,結果跑的都很快。以後看T3,這不是Cooook講的原題嘛,操,我不會SAM,由於記得他當時說SA不能作,就沒想,寫了個30分kmp暴力,以後又去yyT1,而後yy出了那個O(n^2)的暴力,而後寫,寫完和狀壓拍,拍上了,而後想優化,發現我這些操做就是一個線段樹,而後趕忙碼上,拍上了,而後感受今天這題豈不是會有不少人AK,然而我掛在了一道原題上。。以後又靜態查了波錯就完了。100+100+30=230 rank2/10,沒有掛分,不錯,沒有人AK??有點難以想象。數據結構
T1,f[i][j]表示前i個位置,第i個位置水的高度是j的答案,cnt[i][j]=i這個位置j高度的水能知足多少條件。ide
轉移的話:$$f[i][j]=Max_{k=0}^{h[i]} (f[i-1][k]+cnt[i][j]) (j<=h[i])$$函數
$$f[i][j]=f[i-1][j]+cnt[i][j] (j>h[i])$$
而後這個加法和去Max均可以經過線段樹來操做,就能夠O(nlogn)了,貌似正解是樹形dp??
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #define N 100050 6 using namespace std; 7 int T,n,m,ans,h[N],num[N<<1],num_cnt; 8 struct data{int x,y,o;}d[N]; 9 inline bool cmp(data a,data b){ 10 if(a.x==b.x)return a.y<b.y; 11 return a.x<b.x; 12 } 13 int maxn[N<<3],tag[N<<3],lazy[N<<3]; 14 inline void pushdown(int rt){ 15 if(tag[rt]){ 16 maxn[rt<<1]=tag[rt<<1]=tag[rt]; 17 lazy[rt<<1]=0; 18 maxn[rt<<1|1]=tag[rt<<1|1]=tag[rt]; 19 lazy[rt<<1|1]=0; 20 tag[rt]=0; 21 } 22 if(lazy[rt]){ 23 maxn[rt<<1]+=lazy[rt]; 24 lazy[rt<<1]+=lazy[rt]; 25 maxn[rt<<1|1]+=lazy[rt]; 26 lazy[rt<<1|1]+=lazy[rt]; 27 lazy[rt]=0; 28 } 29 } 30 void update(int rt,int l,int r,int x,int y,int z){ 31 if(x<=l&&r<=y){ 32 maxn[rt]+=z;lazy[rt]+=z; 33 return ; 34 } 35 pushdown(rt); 36 int mid=(l+r)>>1; 37 if(x<=mid)update(rt<<1,l,mid,x,y,z); 38 if(y>mid)update(rt<<1|1,mid+1,r,x,y,z); 39 maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]); 40 } 41 void change(int rt,int l,int r,int x,int y,int z){ 42 if(x<=l&&r<=y){ 43 maxn[rt]=tag[rt]=z;lazy[rt]=0; 44 return ; 45 } 46 pushdown(rt); 47 int mid=(l+r)>>1; 48 if(x<=mid)change(rt<<1,l,mid,x,y,z); 49 if(y>mid)change(rt<<1|1,mid+1,r,x,y,z); 50 maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]); 51 } 52 int query(int rt,int l,int r,int x,int y){ 53 if(x<=l&&r<=y)return maxn[rt]; 54 pushdown(rt); 55 int mid=(l+r)>>1; 56 if(y<=mid)return query(rt<<1,l,mid,x,y); 57 if(x>mid)return query(rt<<1|1,mid+1,r,x,y); 58 return max(query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y)); 59 } 60 inline int read(){ 61 int a=0;char ch=getchar(); 62 while(ch<'0'||ch>'9')ch=getchar(); 63 while(ch>='0'&&ch<='9'){a=a*10+(ch^48);ch=getchar();} 64 return a; 65 } 66 int main(){ 67 register int i,l,r,mx; 68 T=read(); 69 while(T--){ 70 n=read();m=read(); 71 num_cnt=0; 72 for(i=1;i<n;++i){ 73 h[i]=read(); 74 num[++num_cnt]=h[i]; 75 } 76 for(i=1;i<=m;++i){ 77 d[i].x=read();d[i].y=read();d[i].o=read(); 78 num[++num_cnt]=++d[i].y; 79 } 80 sort(d+1,d+m+1,cmp); 81 sort(num+1,num+num_cnt+1); 82 num_cnt=unique(num+1,num+num_cnt+1)-num-1; 83 for(i=1;i<n;++i) 84 h[i]=lower_bound(num+1,num+num_cnt+1,h[i])-num; 85 for(i=1;i<=m;++i) 86 d[i].y=lower_bound(num+1,num+num_cnt+1,d[i].y)-num; 87 memset(maxn,0,sizeof maxn); 88 memset(tag,0,sizeof tag); 89 memset(lazy,0,sizeof lazy); 90 for(i=1,l=1,r=0;i<=n;++i){ 91 while(r<m&&d[r+1].x==i)++r; 92 for(;l<=r;++l){ 93 if(d[l].o)update(1,0,num_cnt,d[l].y,num_cnt,1); 94 else update(1,0,num_cnt,0,d[l].y-1,1); 95 } 96 mx=query(1,0,num_cnt,0,h[i]); 97 change(1,0,num_cnt,0,h[i],mx); 98 } 99 printf("%d\n",maxn[1]); 100 } 101 }
T2,裸的二分圖博弈,不解釋。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 #define N 10050 8 #define inf 0x3fffffff 9 using namespace std; 10 int e=2,head[N]; 11 struct edge{ 12 int u,v,next; 13 }ed[N<<5]; 14 void add(int u,int v){ 15 ed[e].u=u;ed[e].v=v; 16 ed[e].next=head[u];head[u]=e++; 17 } 18 char s[105]; 19 int n,m,can[105][105],id[105][105],tot1,tot2,cnt; 20 int ans[N],bo[N],pp[N]; 21 bool find(int x){ 22 for(int i=head[x];i;i=ed[i].next){ 23 int v=ed[i].v; 24 if(!bo[v]){ 25 bo[v]=1; 26 if(!pp[v]||find(pp[v])){ 27 pp[v]=x; 28 pp[x]=v; 29 return 1; 30 } 31 } 32 } 33 return 0; 34 } 35 void dfs(int x,int o){ 36 bo[x]=1; 37 // printf("x====%d %d\n",x,o); 38 if(!o){ 39 ans[x]=1; 40 for(int i=head[x];i;i=ed[i].next){ 41 int v=ed[i].v; 42 if(!bo[v])dfs(v,o^1); 43 } 44 } 45 else dfs(pp[x],o^1); 46 } 47 int main(){ 48 // freopen("test.in","r",stdin); 49 // freopen("2.out","w",stdout); 50 scanf("%d%d",&n,&m); 51 for(int i=1;i<=n;i++){ 52 scanf("%s",s+1); 53 for(int j=1;j<=m;j++)if(s[j]=='.'){ 54 can[i][j]=1; 55 if((i+j)&1)id[i][j]=++tot1; 56 else id[i][j]=++tot2; 57 } 58 } 59 for(int i=1;i<=n;i++) 60 for(int j=1;j<=m;j++)if(can[i][j]){ 61 if(!((i+j)&1))id[i][j]+=tot1; 62 // printf("%d %d %d\n",i,j,id[i][j]); 63 } 64 65 for(int i=1;i<=n;i++) 66 for(int j=1;j<m;j++)if(can[i][j]&&can[i][j+1]){ 67 add(id[i][j],id[i][j+1]); 68 add(id[i][j+1],id[i][j]); 69 } 70 for(int i=1;i<n;i++) 71 for(int j=1;j<=m;j++)if(can[i][j]&&can[i+1][j]){ 72 add(id[i][j],id[i+1][j]); 73 add(id[i+1][j],id[i][j]); 74 } 75 76 for(int i=1;i<=tot1;i++){ 77 memset(bo,0,sizeof bo); 78 find(i); 79 } 80 for(int i=1;i<=tot1+tot2;i++)if(!pp[i]){ 81 memset(bo,0,sizeof bo); 82 dfs(i,0); 83 } 84 for(int i=1;i<=n;i++) 85 for(int j=1;j<=m;j++)if(can[i][j]&&ans[id[i][j]])cnt++; 86 printf("%d\n",cnt); 87 for(int i=1;i<=n;i++) 88 for(int j=1;j<=m;j++)if(can[i][j]&&ans[id[i][j]])printf("%d %d\n",i,j); 89 return 0; 90 }
T3,後綴自動機,分類討論。當$k>\sqrt{n}$時,咱們暴力跑,時間複雜度O(mqlogn)。不然咱們對於每一個串暴力O(k^2)在後綴自動機上跑,對於每一個區間的貢獻,離線用莫隊來維護,時間複雜度$O(m\sqrt{m}+qk^{2})$。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 #define LL long long 8 #define N 100500 9 using namespace std; 10 int n,m,q,K,last,tot,l[N],r[N]; 11 char s[N]; 12 int ch[N<<2][26],mx[N<<2],par[N<<2],size[N<<2]; 13 int e=1,head[N<<2]; 14 struct edge{ 15 int u,v,next; 16 }ed[N<<2]; 17 void add(int u,int v){ 18 ed[e].u=u;ed[e].v=v; 19 ed[e].next=head[u];head[u]=e++; 20 } 21 void extend(int c,int o){ 22 int p=last; 23 if(ch[p][c]){ 24 int q=ch[p][c]; 25 if(mx[q]==mx[p]+1){last=q;return ;} 26 int nq=++tot;par[nq]=par[q];mx[nq]=mx[p]+1; 27 memcpy(ch[nq],ch[q],sizeof ch[nq]); 28 for(;p&&ch[p][c]==q;p=par[p])ch[p][c]=nq; 29 par[q]=nq; 30 last=nq;return; 31 } 32 int np=++tot;mx[np]=mx[p]+1;size[np]=o; 33 for(;p&&!ch[p][c];p=par[p])ch[p][c]=np; 34 if(!p)par[np]=1; 35 else{ 36 int q=ch[p][c]; 37 if(mx[q]==mx[p]+1)par[np]=q; 38 else{ 39 int nq=++tot;par[nq]=par[q];mx[nq]=mx[p]+1; 40 memcpy(ch[nq],ch[q],sizeof ch[nq]); 41 for(;p&&ch[p][c]==q;p=par[p])ch[p][c]=nq; 42 par[q]=par[np]=nq; 43 } 44 } 45 last=np; 46 } 47 int a[N],b[N]; 48 namespace work1{ 49 char t[N]; 50 int fa[N<<2][22]; 51 LL ans; 52 vector <int> pp[405]; 53 void dfs(int x,int d){ 54 for(int i=1;(1<<i)<=d;i++) 55 fa[x][i]=fa[fa[x][i-1]][i-1]; 56 for(int i=head[x];i;i=ed[i].next){ 57 int v=ed[i].v; 58 fa[v][0]=x;dfs(v,d+1); 59 size[x]+=size[v]; 60 } 61 } 62 int find(int x,int l){ 63 for(int i=20;~i;i--) 64 if(mx[fa[x][i]]>=l)x=fa[x][i]; 65 return x; 66 } 67 void Main(){ 68 for(int i=1;i<=q;i++){ 69 scanf("%s%d%d",t+1,&a[i],&b[i]); 70 a[i]++;b[i]++; 71 last=1; 72 pp[i].push_back(last); 73 for(int j=1;j<=K;j++){ 74 extend(t[j]-'a',0); 75 pp[i].push_back(last); 76 } 77 } 78 for(int i=1;i<=tot;i++)add(par[i],i); 79 dfs(1,1); 80 for(int i=1;i<=q;i++){ 81 ans=0; 82 for(int j=a[i];j<=b[i];j++) 83 ans+=size[find(pp[i][r[j]],r[j]-l[j]+1)]; 84 printf("%lld\n",ans); 85 } 86 return ; 87 } 88 } 89 namespace work2{ 90 int be[N]; 91 int cnt[444][444]; 92 LL ans[N]; 93 struct data{ 94 char t[444]; 95 int a,b,id; 96 }d[N]; 97 bool cmp(data a,data b){ 98 if(be[a.a]==be[b.a])return a.b<b.b; 99 return be[a.a]<be[b.a]; 100 } 101 LL query(data x){ 102 LL ans=0; 103 for(int i=1;i<=K;i++){ 104 for(int j=i,now=1;j<=K;j++){ 105 if(!ch[now][x.t[j]-'a'])break; 106 now=ch[now][x.t[j]-'a']; 107 ans+=1ll*size[now]*cnt[i][j]; 108 } 109 } 110 return ans; 111 } 112 void dfs(int x){ 113 for(int i=head[x];i;i=ed[i].next){ 114 int v=ed[i].v; 115 dfs(v); 116 size[x]+=size[v]; 117 } 118 } 119 void Main(){ 120 for(int i=1;i<=tot;i++)add(par[i],i); 121 dfs(1); 122 for(int i=1;i<=q;i++){ 123 d[i].id=i; 124 scanf("%s%d%d",d[i].t+1,&d[i].a,&d[i].b); 125 d[i].a++;d[i].b++; 126 } 127 int mm=sqrt(m); 128 for(int i=1;i<=m;i++)be[i]=(i-1)/mm+1; 129 sort(d+1,d+q+1,cmp); 130 int posl=1,posr=0; 131 for(int i=1;i<=q;i++){ 132 while(posl<d[i].a)cnt[l[posl]][r[posl]]--,posl++; 133 while(posl>d[i].a)posl--,cnt[l[posl]][r[posl]]++; 134 while(posr<d[i].b)posr++,cnt[l[posr]][r[posr]]++; 135 while(posr>d[i].b)cnt[l[posr]][r[posr]]--,posr--; 136 ans[d[i].id]=query(d[i]); 137 } 138 for(int i=1;i<=q;i++)printf("%lld\n",ans[i]); 139 } 140 } 141 int main(){ 142 scanf("%d%d%d%d",&n,&m,&q,&K); 143 scanf("%s",s+1); 144 last=++tot; 145 for(int i=1;i<=n;i++)extend(s[i]-'a',1); 146 for(int i=1;i<=m;i++)scanf("%d%d",&l[i],&r[i]),l[i]++,r[i]++; 147 if(K>sqrt(n))work1::Main(); 148 else work2::Main(); 149 return 0; 150 }
4.19
開場看T1,發現和原來作的商店購物有點像,估計是一堆組合數亂搞,先放放。看T2,裸fwt啊!裸的fwt有五十分,而後發現如今要求$x+x^{2}+x^{4}+x^{8}....$,而後我玄學的亂猜了個結論,這個會有循環節,而後就打出來了,發現好像是對的。就去看T3,只會30分暴力,以後一直在想從誰走到誰會作出多少貢獻,發現機率不一樣,貢獻也不一樣,以後趕忙去把T1的50分暴力打上了,而後想到了容斥,沒時間打了。GG。40+100+30=170 rank1/10。T1up沒有減一掛了10分。
T1,容斥前幾個有幾個不合法,而後直接組合數,組合數要用exLucas,而後我發現我原來學了一個假的exLucas,很是優秀。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 using namespace std; 8 int read(){ 9 int a=0;char ch=getchar(); 10 while(ch<'0'||ch>'9')ch=getchar(); 11 while(ch>='0'&&ch<='9'){a=a*10+(ch^48);ch=getchar();} 12 return a; 13 } 14 int T,mod,n,n1,n2,m,ans,up[12]; 15 int cnt[266],p[10],pk[10],K[10],r[10],num,fac[10][11111]; 16 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 17 int qp(int a,int b,int c){ 18 int ans=1; 19 while(b){ 20 if(b&1)ans=1ll*ans*a%c; 21 a=1ll*a*a%c; b>>=1; 22 } 23 return ans; 24 } 25 #define pr pair<int,int> 26 #define fir first 27 #define sec second 28 pr calc(int n,int x){ 29 if(!n)return pr(1,0); 30 int a=qp(fac[x][pk[x]-1],n/pk[x],pk[x]); 31 int b=n/p[x]; 32 pr ans=calc(n/p[x],x); 33 a=1ll*a*fac[x][n%pk[x]]%mod; 34 ans.fir=1ll*ans.fir*a%pk[x]; 35 ans.sec+=b; 36 return ans; 37 } 38 int C(int n,int m,int x){ 39 if(m>n||m<0)return 0; 40 if(m==n||m==0)return 1; 41 pr ans1=calc(n,x),ans2=calc(m,x),ans3=calc(n-m,x); 42 int a=1ll*ans1.fir 43 *qp(ans2.fir,pk[x]/p[x]*(p[x]-1)-1,pk[x])%pk[x] 44 *qp(ans3.fir,pk[x]/p[x]*(p[x]-1)-1,pk[x])%pk[x]; 45 int b=ans1.sec-ans2.sec-ans3.sec; 46 if(b>=K[x])return 0; 47 return 1ll*a*qp(p[x],b,pk[x])%pk[x]; 48 } 49 int crt(){ 50 int ans=0; 51 for(int i=1,tmp;i<=num;i++){ 52 tmp=qp(mod/pk[i],pk[i]/p[i]*(p[i]-1)-1,pk[i]); 53 UPD(ans,1ll*(mod/pk[i])*tmp%mod*r[i]%mod); 54 } 55 return ans; 56 } 57 int getc(int n,int m){ 58 if(m>n||m<0)return 0; 59 if(m==n||m==0)return 1; 60 for(int i=1;i<=num;i++){ 61 r[i]=C(n,m,i); 62 } 63 return crt(); 64 } 65 int main(){ 66 register int i,j,sum,now; 67 T=read();mod=read(); 68 if(mod==10007)num=1,p[1]=pk[1]=10007,K[1]=1; 69 if(mod==262203414){ 70 p[1]=pk[1]=2,p[2]=pk[2]=3,p[3]=pk[3]=11,p[4]=pk[4]=397,p[5]=pk[5]=10007; 71 K[1]=K[2]=K[3]=K[4]=K[5]=1;num=5; 72 } 73 if(mod==437367875){ 74 num=K[1]=K[2]=3;K[3]=2; 75 p[1]=5;pk[1]=125;p[2]=7;pk[2]=343;p[3]=101;pk[3]=10201; 76 } 77 for(i=1;i<=num;i++){ 78 fac[i][0]=1; 79 for(int j=1;j<pk[i];j++) 80 if(j%p[i])fac[i][j]=1ll*fac[i][j-1]*j%pk[i]; 81 else fac[i][j]=fac[i][j-1]; 82 } 83 while(T--){ 84 ans=0; 85 n=read();n1=read();n2=read();m=read()-n; 86 for(i=1;i<=n1;++i)up[i]=read(); 87 for(i=n1+1;i<=n1+n2;++i)m-=read()-1; 88 for(i=1;i<=n1;++i)up[i]--; 89 for(i=0;i<(1<<n1);i++){ 90 cnt[i]=cnt[i>>1]+(i&1); 91 for(j=1,sum=0;j<=n1;j++)if(i&(1<<j-1)) 92 sum+=up[j]+1; 93 now=getc(m-sum+n-1,n-1); 94 if(cnt[i]&1)ans=(ans-now+mod)%mod; 95 else UPD(ans,now); 96 } 97 printf("%d\n",ans); 98 } 99 return 0; 100 }
T2,考場打的循環節實際上是有理論依據的,咱們如今實際上是要求最小的x知足$2^{x}=2 (mod \; \phi{p})$,而後咱們會發現這個x等於5003,其實這裏用到了ex歐拉定理,其實也是由於2比較特殊。更優秀一點的作法是倍增求解,咱們須要倍增處理出$x^{2^{2^{a}}}$和$\sum_{i=0}^{a}{x^{2^{2^{i}}}}$,而後直接上fwt就能夠了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <ctime> 7 #define N 277777 8 #define mod 10007 9 using namespace std; 10 int a[N],n,m,p,ans,all; 11 int inv2=5004; 12 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 13 void fwt(int *a){ 14 register int i,j,k,x,y; 15 for(k=2;k<=all;k<<=1) 16 for(i=0;i<all;i+=k) 17 for(j=0;j<(k>>1);j++){ 18 x=a[i+j],y=a[i+j+(k>>1)]; 19 a[i+j]=(x+y)%mod; 20 a[i+j+(k>>1)]=(x-y+mod)%mod; 21 } 22 } 23 void ifwt(int *a){ 24 register int i,j,k,x,y; 25 for(k=2;k<=all;k<<=1) 26 for(i=0;i<all;i+=k) 27 for(j=0;j<(k>>1);j++){ 28 x=a[i+j],y=a[i+j+(k>>1)]; 29 a[i+j]=(x+y)*inv2%mod; 30 a[i+j+(k>>1)]=(x-y+mod)*inv2%mod; 31 } 32 } 33 int sum[mod+10],vis[mod+10],tim[mod+10]; 34 int s1[mod+10],pos[mod+10],val[mod+10],len[mod+10],s2[mod+10]; 35 int pp[mod+10]; 36 void work(){ 37 int now,cnt; 38 for(int i=1;i<mod;i++){ 39 now=i;cnt=1; 40 sum[cnt]=now; 41 vis[now]=i; 42 tim[now]=cnt; 43 while(vis[now*now%mod]!=i){ 44 now=now*now%mod;cnt++; 45 sum[cnt]=(sum[cnt-1]+now)%mod; 46 vis[now]=i;tim[now]=cnt; 47 } 48 now=now*now%mod; 49 s1[i]=sum[tim[now]-1]; 50 pos[i]=tim[now]; 51 val[i]=now; 52 len[i]=cnt-tim[now]+1; 53 s2[i]=(sum[cnt]-sum[tim[now]-1]+mod)%mod; 54 } 55 m++; 56 for(int i=1;i<mod;i++){ 57 if(m<pos[i]){ 58 now=i; 59 for(int j=1;j<=m;j++){ 60 UPD(pp[i],now); 61 now=now*now%mod; 62 } 63 } 64 else{ 65 pp[i]=s1[i]; 66 int l=(m-pos[i]+1); 67 UPD(pp[i],(l/len[i])%mod*s2[i]%mod); 68 l%=len[i];now=val[i]; 69 for(int j=1;j<=l;j++){ 70 UPD(pp[i],now); 71 now=now*now%mod; 72 } 73 } 74 } 75 for(int i=0;i<all;i++)a[i]=pp[a[i]]; 76 } 77 int main(){ 78 scanf("%d%d%d",&n,&m,&p); 79 all=(1<<n); 80 for(int i=0;i<all;i++)scanf("%d",&a[i]); 81 fwt(a);work();ifwt(a); 82 printf("%d\n",a[p]); 83 }
T3,咱們考慮把環拆成一個序列,而後咱們dp時就是欽定該段只剩最後一個元素是點,而後求出從初始狀態到該狀態的指望和機率,轉移時再枚舉剩下的點中誰是最後一個變成X的,而後就變成了咱們已知的f值,這樣區間dp下去就能夠了。
具體的轉移方程:f表機率,g表指望,p表示l~r這段除r外最後變成X的.的位置是k的機率
$$p(l,r,k)={\frac{len(l,k)}{len(l,r)}}^{num(l,k)} {\frac{len(k+1,r)}{len(l,r)}}^{num(k+1,r)-1}*C_{num(l,r)-2}^{num(l,k)-1}g(l,k)g(k+1,r)$$
$$g(l,r)=\sum_{k=l}^{r-1}{p(l,r,k)}$$
$$f(l,r)=\frac{1}{g(l,r)} \sum_{k=l}^{r-1}{p(l,r,k)(f(l,k)+f(k+1,r)+\frac{k-i}{2})}$$
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 205 7 #define nxt(x) (((x)==n)?(1):((x)+1)) 8 #define pre(x) (((x)==1)?(n):((x)-1)) 9 using namespace std; 10 char s[N]; 11 int visf[N][N],visg[N][N],len[N][N],cnt[N][N],n,T; 12 double f[N][N],g[N][N],C[N][N],pw[N][N],ans; 13 double P(int l,int r,int k); 14 double G(int l,int r); 15 double F(int l,int r); 16 double P(int l,int r,int k){ 17 if(s[r]=='X'||s[k]=='X')return 0; 18 int c1=cnt[l][k]-1,c2=cnt[nxt(k)][r]-1; 19 return C[c1+c2][c1]*pw[len[l][k]][c1+1]*pw[len[nxt(k)][r]][c2]/pw[len[l][r]][c1+c2+1]*G(l,k)*G(nxt(k),r); 20 } 21 double G(int l,int r){ 22 if(visg[l][r])return g[l][r]; 23 if(s[r]=='X')return 0; 24 if(cnt[l][r]==1)return 1; 25 double ans=0; 26 for(int i=l;i!=r;i=nxt(i)) 27 ans+=P(l,r,i); 28 visg[l][r]=1; 29 return g[l][r]=ans; 30 } 31 double F(int l,int r){ 32 if(visf[l][r])return f[l][r]; 33 if(s[r]=='X')return 0; 34 if(cnt[l][r]==1)return 0; 35 if(G(l,r)<1e-12)return 0; 36 double ans=0; 37 for(int i=l;i!=r;i=nxt(i)) 38 ans+=P(l,r,i)*(F(l,i)+F(nxt(i),r)+(len[l][i]-1)/2.0); 39 visf[l][r]=1; 40 return f[l][r]=ans/G(l,r); 41 } 42 int main(){ 43 scanf("%d",&T); 44 for(int i=0;i<=200;i++){ 45 C[i][0]=1; 46 for(int j=1;j<=i;j++) 47 C[i][j]=C[i-1][j-1]+C[i-1][j]; 48 } 49 for(int i=1;i<=200;i++){ 50 pw[i][0]=1; 51 for(int j=1;j<=200;j++) 52 pw[i][j]=pw[i][j-1]*i; 53 } 54 while(T--){ 55 scanf("%s",s+1); 56 n=strlen(s+1); 57 memset(cnt,0,sizeof cnt); 58 for(int i=1;i<=n;i++){ 59 cnt[i][i]=(s[i]=='.'); 60 len[i][i]=1; 61 for(int j=nxt(i);j!=i;j=nxt(j)) 62 cnt[i][j]=cnt[i][pre(j)]+(s[j]=='.'), 63 len[i][j]=len[i][pre(j)]+1; 64 } 65 if(!cnt[1][n]){puts("0");continue;} 66 memset(visf,0,sizeof visf); 67 memset(visg,0,sizeof visg); 68 ans=0; 69 for(int i=1;i<=n;i++) 70 ans+=G(nxt(i),i)*F(nxt(i),i); 71 printf("%0.8f\n",ans+(n-1)/2.0); 72 } 73 return 0; 74 }
4.22
怎麼又考試啊。先看T1,35分sb杜教篩phi,20分暴力,看起來很好,感受又是組合數亂搞?看T2,只會20分裸暴力,yy了一會循環節,可是以爲至少是O(p)的,就沒深刻想,而後看T3,多項式?卷積?不錯,這不是裸的多點求值嘛!yy了一會,不會,可是感受這確定不是正解,而後又亂yy了一會,啥也不會,而後哪道題都不會了,就GG了。40+0+30=70 rank10/10,T1傻逼暴力掛了,T2矩陣中個人-1沒有+mod爆負了,而後就掛了。
T1,容斥最後gcd的質因子,$$\sum_{i=1}^{n}{\mu{(i)} \cdot C_{n/i+k-1}^{k}}$$須要杜教篩mu,而後除法分塊。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <map> 7 #define mod 1000000007 8 #define N 10000050 9 using namespace std; 10 int tot,mu[N],sm[N],prime[666666],T,n,m,ans; 11 int inv[1000500],fac[1000500],Inv; 12 bool vis[N]; 13 void init(){ 14 mu[1]=sm[1]=1; 15 for(int i=2;i<=10000000;i++){ 16 if(!vis[i]){ 17 prime[++tot]=i; 18 mu[i]=mod-1; 19 } 20 for(int j=1;j<=tot&&i*prime[j]<=10000000;j++){ 21 vis[i*prime[j]]=1; 22 if(i%prime[j]==0){ 23 mu[i*prime[j]]=0; 24 break; 25 } 26 mu[i*prime[j]]=mod-mu[i]; 27 } 28 sm[i]=(sm[i-1]+mu[i])%mod; 29 } 30 } 31 map<int,int> mm; 32 int gets(int n){ 33 if(n<=10000000)return sm[n]; 34 if(mm.count(n))return mm[n]; 35 int ans=1; 36 for(int i=2,j;i<=n;i=j+1){ 37 j=n/(n/i); 38 ans=(ans-1ll*(j-i+1)*gets(n/i)%mod+mod)%mod; 39 } 40 return mm[n]=ans; 41 } 42 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 43 int qp(int a,int b){ 44 int c=1; 45 for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)c=1ll*c*a%mod; 46 return c; 47 } 48 int C(int n){ 49 int ans=Inv; 50 if(n<=1000000)ans=1ll*ans*fac[n]%mod; 51 else for(int i=1;i<=m;i++)ans=1ll*ans*(n-i+1)%mod; 52 return ans; 53 } 54 int main(){ 55 //freopen("test.in","r",stdin); 56 init(); 57 inv[1]=1; 58 for(int i=2;i<=1000000;i++) 59 inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod; 60 scanf("%d",&T); 61 while(T--){ 62 scanf("%d%d",&n,&m); 63 fac[m]=1; 64 for(int i=1;i<=m;i++)fac[m]=1ll*fac[m]*i%mod; 65 for(int i=m+1;i<=1000000;i++) 66 fac[i]=1ll*fac[i-1]*i%mod*inv[i-m]%mod; 67 Inv=qp(fac[m],mod-2); 68 ans=0; 69 for(int i=1,j;i<=n;i=j+1){ 70 j=n/(n/i); 71 UPD(ans,1ll*(gets(j)-gets(i-1)+mod)%mod*C(n/i+m-1)%mod); 72 } 73 printf("%d\n",ans); 74 } 75 return 0; 76 }
T2,暴力找循環節,而後用bsgs的思想$O(\sqrt{p})$作就能夠了。可是複雜度不夠優秀,咱們考慮打表找規律,f[i]表示%i意義下的循環節長度,能夠發現,若$(x,y)=1$,$f[x*y]=lcm(f[x],f[y])$,若$x=p^{k}$ ,$f[x]=f[p] \cdot p^{k-1}$,而後若$p%10=1|p%10=9$,$f[i]=p-1$,而後這樣須要作bsgs的數就不多了,就能夠愉快的AC了。
1 #pragma GCC optimize ("O3") 2 #include <bits/stdc++.h> 3 #define int unsigned long long 4 using namespace std; 5 int a,b,n,k,p,T,len[105]; 6 struct mart{ 7 int a[2][2]; 8 mart operator * (mart B){ 9 mart C; 10 C.a[0][0]=(a[0][0]*B.a[0][0]%p+a[0][1]*B.a[1][0]%p)%p; 11 C.a[0][1]=(a[0][0]*B.a[0][1]%p+a[0][1]*B.a[1][1]%p)%p; 12 C.a[1][0]=(a[1][0]*B.a[0][0]%p+a[1][1]*B.a[1][0]%p)%p; 13 C.a[1][1]=(a[1][0]*B.a[0][1]%p+a[1][1]*B.a[1][1]%p)%p; 14 return C; 15 } 16 }A,B,d,e,f; 17 mart qp(mart a,int b){ 18 mart c; 19 c.a[0][0]=c.a[1][1]=1; 20 c.a[0][1]=c.a[1][0]=0; 21 for(;b;b>>=1,a=a*a) 22 if(b&1)c=c*a; 23 return c; 24 } 25 int getg(int n){ 26 if(!n)return a%p; 27 A.a[0][0]=3;A.a[0][1]=1; 28 A.a[1][0]=p-1;A.a[1][1]=0; 29 B.a[0][0]=b%p;B.a[0][1]=a%p; 30 B.a[1][0]=B.a[1][1]=0; 31 B=B*qp(A,n-1); 32 return B.a[0][0]; 33 } 34 unordered_map<int,int> hh; 35 unordered_map<int,int> mm; 36 int getp(int n){ 37 if(n%10==1||n%10==9)return n-1; 38 if(mm.count(n))return mm[n]; 39 hh.clear();p=n; 40 int x=ceil(sqrt(2*n)),last=0,now=1,tmp; 41 d.a[0][0]=1;d.a[0][1]=0;d.a[1][0]=d.a[1][1]=0; 42 e.a[0][0]=3;e.a[0][1]=1;e.a[1][0]=p-1;e.a[1][1]=0; 43 f.a[0][0]=f.a[1][1]=1;f.a[0][1]=f.a[1][0]=0; 44 for(int i=0;i<x;i++){ 45 if(hh.count(now*1000000007+last))return i; 46 hh[now*1000000007+last]=i; 47 tmp=now;now=(now*3%p-last+p)%p;last=tmp; 48 f=f*e; 49 } 50 d=d*f*f; 51 for(int i=1;i<=x;i++,d=d*f){ 52 if(hh.count(d.a[0][0]*1000000007+d.a[0][1])) 53 return mm[n]=(i+1)*x-hh[d.a[0][0]*1000000007+d.a[0][1]]; 54 } 55 } 56 int gcd(int x,int y){return !y?x:gcd(y,x%y);} 57 int lcm(int x,int y){return x/gcd(x,y)*y;} 58 int getl(int x){ 59 if(mm.count(x))return mm[x]; 60 int y=x,ans=1; 61 for(int i=2;i*i<=y;i++)if(y%i==0){ 62 int w=getp(i);y/=i; 63 while(y%i==0)w=w*i,y/=i; 64 ans=lcm(ans,w); 65 } 66 if(y!=1)ans=lcm(ans,getp(y)); 67 return mm[x]=ans; 68 } 69 signed main(){ 70 scanf("%lld",&T); 71 while(T--){ 72 scanf("%lld%lld%lld%lld%lld",&a,&b,&n,&k,&p); 73 len[1]=p; 74 for(int i=2;i<=k;i++)len[i]=getl(len[i-1]); 75 for(int i=k;i;i--)p=len[i],n=getg(n); 76 printf("%lld\n",n); 77 } 78 return 0; 79 }
T3,真$\cdot$神題。首先若是c=0,能夠直接暴力。
咱們考慮$b=0$的狀況,咱們如今要求
$$y_{p}=\sum_{i=0}^{n-1}{A[i]*x_{p}^{i}}$$
$$\sum_{i=0}^{n-1}{A[i] \sum_{j=0}^{i} C_{i}^{j} \cdot d^{j} \cdot e^{i-j} \cdot c^{2pj}}$$
$$\sum_{j=0}^{n-1}{ c^{(p+j)^{2}-p^{2}-j^{2}} \cdot d^{j} \cdot \frac{1}{j!} \sum _{i=j+k}{A[i] \cdot {i!} \cdot e^{k} \cdot \frac{1}{k!} } }$$
$$\frac{1}{c^{p^{2}}} \sum_{x=p+j}{ c^{x^{2}} \cdot d^{j} \cdot \frac{1}{c^{j^{2}}} \cdot \frac{1}{j!} \sum_{i=j+k}{A[i] \cdot {i!} \cdot e^{k} \cdot \frac{1}{k!} } }$$
而後咱們就能夠經過兩次卷積來統計這個答案啦。
因而咱們就愉快的解決了$b=0$的狀況。
下面考慮通解,咱們發現$bc^{4k}+dc^{2k}+e$這個式子很不美麗,因而咱們考慮將其化成$b(c^{2k}+d’)^{2}+e’$,解方程解得$d'=\frac{d}{2b}$,$e'=e-\frac{d^{2}}{4b}$。
ps.下面的d即爲d',e即爲e'。
因此咱們如今要求的就是
$$\sum_{i=0}^{n-1}{A[i] (b(c^{2p}+d)^{2}+e)^{i} }$$
$$\sum_{i=0}^{n-1}{A[i] \sum_{j=0}^{i} C_{i}^{j} \cdot b^{j} \cdot (c^{2p}+d)^{2j} \cdot e^{i-j} }$$
$$\sum_{j=0}^{n-1} { (c^{2p}+d)^{2j} \cdot b^{j} \cdot \frac{1}{j!} \sum_{i=j+k} {A[i] \cdot i! \cdot e^{k} \cdot \frac{1}{k!} } }$$
咱們按照上面$b=0$的作法將後面的東西卷積,如今咱們就是要求
$$\sum_{j=0}^{n-1} { (c^{2p}+d)^{2j} \cdot A[j] }$$
$$\sum_{j=0}^{n-1} { A[j] \sum_{k+l=2j}{ C_{2j}^{k} \cdot c^{(p+k)^{2}-p^{2}-k^{2}} \cdot d^{l} } }$$
$$\frac{1}{c^{p^{2}}} \sum_{x=p+k} { c^{x^{2}} \cdot \frac{1}{c^{k^{2}}} \cdot \frac{1}{k!} \sum_{k+l=2j} { d^{l} \cdot \frac{1}{l!} \cdot A[j] \cdot {(2j)!} } } $$
咱們發現到這裏就能夠卷積啦!只是細節比較麻煩。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 555555 7 #define mod 1000003 8 #define LL long long 9 using namespace std; 10 11 int a[N],b[N],c[N],d[N],e[N],f[N],g[N]; 12 int n,B,C,D,E; 13 int pw_b[N],pw_d[N],pw_e[N],pw_c[N],inv_c[N],fac[N],inv[N]; 14 15 LL mul(LL a,LL b,LL p){ 16 return (a*b-(LL)(((long double)a*b+0.5)/(long double)p)*p+p)%p; 17 } 18 int qp(int a,int b,int p=mod){ 19 int c=1; 20 for(;b;b>>=1,a=1ll*a*a%p) 21 if(b&1)c=1ll*c*a%p; 22 return c; 23 } 24 void UPD(int &a,int b){ 25 a=(a+b>=mod)?(a+b-mod):(a+b); 26 } 27 28 struct poly{ 29 int p,g,w[N],rev[N]; 30 void prepare(int l){ 31 w[0]=1;int dan=qp(g,(p-1)/l,p); 32 for(int i=1;i<=l;i++)w[i]=1ll*w[i-1]*dan%p; 33 for(int i=0;i<=l;i++){ 34 if(i&1)rev[i]=(rev[i>>1]>>1)|(l>>1); 35 else rev[i]=rev[i>>1]>>1; 36 } 37 } 38 void dft(int *a,int o,int l){ 39 for(int i=0;i<l;i++) 40 if(i<rev[i])swap(a[i],a[rev[i]]); 41 for(int k=2,t;k<=l;k<<=1){ 42 for(int i=0;i<l;i+=k){ 43 for(int j=0;j<(k>>1);j++){ 44 t=1ll*(o==1?w[l/k*j]:w[l-l/k*j])*a[i+j+(k>>1)]%p; 45 a[i+j+(k>>1)]=(a[i+j]-t+p)%p;a[i+j]=(a[i+j]+t)%p; 46 } 47 } 48 } 49 int inv=qp(l,p-2,p); 50 if(o==-1)for(int i=0;i<l;i++)a[i]=1ll*a[i]*inv%p; 51 } 52 void mul(int *a,int *b,int *c,int l){ 53 static int tmpa[N],tmpb[N]; 54 prepare(l); 55 for(int i=0;i<l;i++)tmpa[i]=a[i],tmpb[i]=b[i]; 56 dft(tmpa,1,l);dft(tmpb,1,l); 57 for(int i=0;i<l;i++)c[i]=1ll*tmpa[i]*tmpb[i]%p; 58 dft(c,-1,l); 59 } 60 void revmul(int *a,int *b,int *c,int l){ 61 static int tmpb[N]; 62 for(int i=0;i<l;i++)tmpb[i]=b[i]; 63 reverse(tmpb,tmpb+l); 64 mul(a,tmpb,c,l); 65 reverse(c,c+l); 66 } 67 }P[2]; 68 void revmul(int *a,int *b,int *c,int l,int l1){ 69 static int tmp[2][N]; 70 int L;for(L=1;L<=l;L<<=1); 71 P[0].revmul(a,b,tmp[0],L); 72 P[1].revmul(a,b,tmp[1],L); 73 LL Mod=1ll*P[0].p*P[1].p,v; 74 for(int i=0;i<l1;i++){ 75 v=0; 76 v=(v+mul(1ll*tmp[0][i]*P[1].p%Mod,1ll*qp(P[1].p,P[0].p-2,P[0].p)%Mod,Mod))%Mod; 77 v=(v+mul(1ll*tmp[1][i]*P[0].p%Mod,1ll*qp(P[0].p,P[1].p-2,P[1].p)%Mod,Mod))%Mod; 78 c[i]=v%mod; 79 } 80 } 81 namespace work1{ 82 void Main(){ 83 int x=(B+D+E)%mod,y=0,now=1; 84 for(int i=0;i<n;i++,now=1ll*now*x%mod) 85 UPD(y,1ll*a[i]*now%mod); 86 printf("%d\n",y); 87 x=E;y=0;now=1; 88 for(int i=0;i<n;i++,now=1ll*now*x%mod) 89 UPD(y,1ll*a[i]*now%mod); 90 for(int i=1;i<n;i++)printf("%d\n",y); 91 } 92 } 93 namespace work2{ 94 void Main(){ 95 fac[0]=1;for(int i=1;i<=2*n;i++)fac[i]=1ll*fac[i-1]*i%mod; 96 inv[2*n]=qp(fac[2*n],mod-2);for(int i=2*n;i;i--)inv[i-1]=1ll*inv[i]*i%mod; 97 pw_d[0]=1;for(int i=1;i<=2*n;i++)pw_d[i]=1ll*pw_d[i-1]*D%mod; 98 pw_e[0]=1;for(int i=1;i<=2*n;i++)pw_e[i]=1ll*pw_e[i-1]*E%mod; 99 for(int i=0;i<=2*n;i++)pw_c[i]=qp(C,1ll*i*i%(mod-1)),inv_c[i]=qp(pw_c[i],mod-2); 100 for(int i=0;i<n;i++)a[i]=1ll*a[i]*fac[i]%mod; 101 for(int i=0;i<n;i++)b[i]=1ll*pw_e[i]*inv[i]%mod; 102 revmul(b,a,c,2*n,n); 103 for(int i=0;i<n;i++)c[i]=1ll*c[i]*inv_c[i]%mod*inv[i]%mod*pw_d[i]%mod; 104 for(int i=0;i<2*n;i++)d[i]=pw_c[i]; 105 revmul(c,d,e,3*n,n); 106 for(int i=0;i<n;i++){ 107 e[i]=1ll*e[i]*inv_c[i]%mod; 108 printf("%d\n",e[i]); 109 } 110 } 111 } 112 namespace work3{ 113 void Main(){ 114 D=1ll*D*qp(2*B,mod-2)%mod; 115 E=(E-1ll*B*D%mod*D%mod+mod)%mod; 116 fac[0]=1;for(int i=1;i<=3*n;i++)fac[i]=1ll*fac[i-1]*i%mod; 117 inv[3*n]=qp(fac[3*n],mod-2);for(int i=3*n;i;i--)inv[i-1]=1ll*inv[i]*i%mod; 118 pw_b[0]=1;for(int i=1;i<=3*n;i++)pw_b[i]=1ll*pw_b[i-1]*B%mod; 119 pw_d[0]=1;for(int i=1;i<=3*n;i++)pw_d[i]=1ll*pw_d[i-1]*D%mod; 120 pw_e[0]=1;for(int i=1;i<=3*n;i++)pw_e[i]=1ll*pw_e[i-1]*E%mod; 121 for(int i=0;i<=3*n;i++)pw_c[i]=qp(C,1ll*i*i%(mod-1)),inv_c[i]=qp(pw_c[i],mod-2); 122 for(int i=0;i<n;i++)a[i]=1ll*a[i]*fac[i]%mod; 123 for(int i=0;i<n;i++)b[i]=1ll*pw_e[i]*inv[i]%mod; 124 revmul(b,a,c,2*n,n); 125 for(int i=2*n-1;~i;i--){ 126 if(i&1)c[i]=0; 127 else c[i]=1ll*c[i>>1]*fac[i]%mod*inv[i>>1]%mod*pw_b[i>>1]%mod; 128 } 129 for(int i=0;i<2*n;i++)d[i]=1ll*pw_d[i]*inv[i]%mod; 130 revmul(d,c,e,4*n,2*n); 131 for(int i=0;i<2*n;i++)e[i]=1ll*e[i]*inv[i]%mod*inv_c[i]%mod; 132 for(int i=0;i<3*n;i++)f[i]=pw_c[i]; 133 revmul(e,f,g,5*n,n); 134 for(int i=0;i<n;i++){ 135 g[i]=1ll*g[i]*inv_c[i]%mod; 136 printf("%d\n",g[i]); 137 } 138 } 139 } 140 int main(){ 141 P[0].p=998244353;P[0].g=3; 142 P[1].p=1004535809;P[1].g=3; 143 scanf("%d%d%d%d%d",&n,&B,&C,&D,&E); 144 for(int i=0;i<n;i++)scanf("%d",&a[i]); 145 if(!C){work1::Main();return 0;} 146 if(!B){work2::Main();return 0;} 147 work3::Main();return 0; 148 }
4.23
開場看T1,第二個樣例不太明白,而後果斷棄療去看T2,怎麼又是這個題啊,三遍了。數據愈來愈強,只會10分暴力。看T3,這這這,矩陣樹+多項式??兩個變量?把另外一個強行設爲$x^{n}$,算了一下複雜度,$O(n^{5}+n^{6})$,貌似很不可過啊,可是感受這個是最可寫的了,而後碼碼碼,過了大樣例,造了組極限數據,90s。。以後卡了卡,卡到了50s,感受很絕望,以後去看T1,玩出來了樣例2,而後我就陷入了一個思惟誤區,以爲每次的決策是肯定的,而後就在想怎麼比較兩個決策的優劣,而後亂搞了很久也沒搞出來,最後打了個假的暴搜,打完就剩20min了,趕忙去把T2的10分暴力寫了。20+10+50=80 rank4/10。
T1,咱們發現問題其實就是要求出每一輪妹子的勝率,咱們設p爲勝率,q爲負率,發現就是要最大化$\frac{p}{q}$,而後咱們二分他,而後倒着dp,或者說貪心?每次按照當前最優策略轉移,就能夠了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define eps 1e-6 7 using namespace std; 8 int n,m1,m2; 9 double f[5050][2050],p[1050][5]; 10 bool check(double x){ 11 for(int i=1;i<=2*n+1;i++){ 12 if(i<=n)f[n+1][i]=-x; 13 if(i==n+1)f[n+1][i]=0; 14 if(i>n+1)f[n+1][i]=1; 15 } 16 double r,s,t,w,d,l; 17 for(int i=n;i;i--){ 18 r=p[i][1],s=p[i][2],t=p[i][3]; 19 for(int j=1;j<=2*n+1;j++){ 20 w=f[i+1][j+1],d=f[i+1][j],l=f[i+1][j-1]; 21 f[i][j]=max(max(r*w+s*d+t*l,s*w+t*d+r*l),t*w+r*d+s*l); 22 } 23 } 24 return f[1][n+1]>0; 25 } 26 int main(){ 27 //freopen("rps0.in","r",stdin); 28 while(scanf("%d%d%d",&n,&m1,&m2)==3&&((n+m1+m2)!=0)){ 29 for(int i=1;i<=n;i++){ 30 scanf("%lf%lf%lf",&p[i][1],&p[i][2],&p[i][3]); 31 p[i][1]/=100.0;p[i][2]/=100.0;p[i][3]/=100.0; 32 } 33 double l=0,r=1000000,mid; 34 while(l+eps<=r){ 35 mid=(l+r)/2.0; 36 if(check(mid))l=mid; 37 else r=mid; 38 } 39 mid=1.0-1.0/(1.0+mid); 40 memset(f,0,sizeof f); 41 f[0][m2+1]=1; 42 for(int i=0;i<=5000;i++){ 43 for(int j=2;j<m1+m2+1;j++){ 44 f[i+1][j-1]+=f[i][j]*(1-mid); 45 f[i+1][j+1]+=f[i][j]*mid; 46 } 47 f[i+1][1]+=f[i][1]; 48 f[i+1][m1+m2+1]+=f[i][m1+m2+1]; 49 } 50 printf("%0.5f\n",f[5001][m1+m2+1]); 51 } 52 return 0; 53 }
T2,咕咕咕
T3,咕咕咕,正解是二維拉格朗日插值,複雜度貌似是$O(n^{5}+n^{4})$,尚未看懂。
可是能夠用高斯消元水過,由於常數比較優秀。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 1666 7 #define mod 1000000007 8 using namespace std; 9 int a[44][44],n,m,n1,n2,b[888][888],c[888],f[888],cnt; 10 int du[100500],dv[100500],dw[100500],ans; 11 int qp(int a,int b){ 12 int c=1; 13 for(;b;b>>=1,a=1ll*a*a%mod) 14 if(b&1)c=1ll*c*a%mod; 15 return c; 16 } 17 void UPD(int &a,int b){ 18 a=(a+b>=mod)?(a+b-mod):(a+b); 19 } 20 int work(){ 21 int ans=1; 22 for(int k=1;k<n;k++){ 23 if(!a[k][k]){ 24 for(int i=k+1;i<n;i++)if(a[i][k]){ 25 for(int j=k;j<n;j++)swap(a[k][j],a[i][j]); 26 ans=mod-ans; 27 break; 28 } 29 } 30 if(!a[k][k])return 0; 31 ans=1ll*ans*a[k][k]%mod; 32 int inv=qp(a[k][k],mod-2); 33 for(int i=k+1;i<n;i++){ 34 int t=1ll*a[i][k]*inv%mod; 35 for(int j=k;j<n;j++) 36 UPD(a[i][j],mod-1ll*t*a[k][j]%mod); 37 } 38 } 39 return ans; 40 } 41 void add(int u,int v,int w){ 42 UPD(a[u][u],w); 43 UPD(a[v][v],w); 44 UPD(a[u][v],mod-w); 45 UPD(a[v][u],mod-w); 46 } 47 void gauss(){ 48 for(int k=1;k<=cnt;k++){ 49 if(!b[k][k]){ 50 for(int i=k+1;i<=cnt;i++)if(b[i][k]){ 51 for(int j=k;j<=cnt;j++)swap(b[k][j],b[i][j]); 52 swap(c[k],c[i]); 53 break; 54 } 55 } 56 int ny=qp(b[k][k],mod-2); 57 for(int i=k+1;i<=cnt;i++){ 58 int t=1ll*b[i][k]*ny%mod; 59 for(int j=k;j<=cnt;j++) 60 UPD(b[i][j],mod-1ll*b[k][j]*t%mod); 61 UPD(c[i],mod-1ll*c[k]*t%mod); 62 } 63 } 64 for(int i=cnt;i;i--){ 65 for(int j=i+1;j<=cnt;j++) 66 UPD(c[i],mod-1ll*b[i][j]*f[j]%mod); 67 f[i]=1ll*c[i]*qp(b[i][i],mod-2)%mod; 68 } 69 } 70 int g[44][44][5]; 71 int main(){ 72 scanf("%d%d%d%d",&n,&m,&n1,&n2); 73 for(int i=1;i<=m;i++){ 74 scanf("%d%d%d",&du[i],&dv[i],&dw[i]); 75 g[du[i]][dv[i]][dw[i]]++; 76 } 77 for(int x=0;x<n;x++){ 78 for(int y=0;y<n-x;y++){ 79 memset(a,0,sizeof a); 80 for(int i=1;i<=n;i++) 81 for(int j=1;j<=n;j++) 82 for(int k=1;k<=3;k++)if(g[i][j][k]){ 83 if(k==1)add(i,j,g[i][j][k]); 84 if(k==2)add(i,j,x*g[i][j][k]); 85 if(k==3)add(i,j,y*g[i][j][k]); 86 } 87 c[++cnt]=work(); 88 for(int i=0,now=0,nx=1;i<n;i++){ 89 for(int j=0,ny=1;j<n-i;j++){ 90 b[cnt][++now]=1ll*nx*ny%mod; 91 ny=1ll*ny*y%mod; 92 } 93 nx=1ll*nx*x%mod; 94 } 95 } 96 } 97 gauss(); 98 for(int i=0,now=1;i<n;i++){ 99 for(int j=0;j<n-i;j++,now++) 100 if(i<=n1&&j<=n2)UPD(ans,f[now]); 101 } 102 printf("%d\n",ans); 103 return 0; 104 }
4.24
先看T1,發現40分sb主席樹亂搞,後面的離線能夠莫隊?而後看T2,看起來能夠線篩+杜教篩,看T3,感受就10分暴力可寫。而後回去碼T1,寫完40分,和暴力拍上了,而後想w=1的,yy了半個多小時,沒有想出來。而後去寫T2,寫了個O(40n)的篩(我是傻逼),又推了推式子,沒推出來,而後拿着k=40的數據去猜k=1的結論,啥也沒發現。而後還有1h左右,在T1的離線和T3的暴力中選擇了T1,寫了30min左右寫完了,感受很開心,發現還有時間去寫T3,而後手賤測了組極限數據,7s。。。而後致力卡常辦小時,仍是沒卡進去。40+30+0=70 rank6/10。這兩天暴力分不是掛了就是沒有拿滿,之後要注意這個問題。
T1,咱們考慮對於每個查詢,能夠改變每一個點做出的貢獻,而後二分答案,計算小於ans且個數小於w的數的個數,因而咱們對於一個權值,將他最後w個的權值附成1,倒數第w+1個的權值設成-w。而後咱們能夠知道對於一個數,他對哪些區間的貢獻是1,-w。這能夠對應到平面上的一個矩形,而後咱們就至關因而矩形加,單點求和。這個能夠主席數套線段樹來作,外層是關於左端點的可持久化權值線段樹,內層是關於右端點的線段樹。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 #define N 100500 8 using namespace std; 9 vector <int> v[N]; 10 int n,w,q,type,a[N],np[N],nnp[N]; 11 int lazy[800*N],ls[800*N],rs[800*N],tot; 12 int root[N],rt[50*N],lon[50*N],ron[50*N],sz; 13 void _update(int &rt,int l,int r,int x,int y,int z){ 14 if(!rt)rt=++tot; 15 if(x<=l&&r<=y){lazy[rt]+=z;return ;} 16 int mid=(l+r)>>1; 17 if(x<=mid)_update(ls[rt],l,mid,x,y,z); 18 if(y>mid)_update(rs[rt],mid+1,r,x,y,z); 19 } 20 void _merge(int o,int &rt,int l,int r){ 21 if(!o)return ; 22 if(!rt){rt=o;return ;} 23 lazy[rt]+=lazy[o]; 24 if(l==r)return ; 25 int mid=(l+r)>>1; 26 _merge(ls[o],ls[rt],l,mid); 27 _merge(rs[o],rs[rt],mid+1,r); 28 } 29 int _query(int o,int rt,int l,int r,int x){ 30 if(l==r)return lazy[rt]-lazy[o]; 31 int mid=(l+r)>>1; 32 if(x<=mid)return _query(ls[o],ls[rt],l,mid,x)+lazy[rt]-lazy[o]; 33 else return _query(rs[o],rs[rt],mid+1,r,x)+lazy[rt]-lazy[o]; 34 } 35 void update(int &rt,int l,int r,int x,int nl,int nr,int nx){ 36 if(!rt)rt=++sz; 37 _update(::rt[rt],1,n,nl,nr,nx); 38 if(l==r)return ; 39 int mid=(l+r)>>1; 40 if(x<=mid)update(lon[rt],l,mid,x,nl,nr,nx); 41 else update(ron[rt],mid+1,r,x,nl,nr,nx); 42 } 43 void merge(int o,int &rt,int l,int r){ 44 if(!o)return ; 45 if(!rt){rt=o;return;} 46 _merge(::rt[o],::rt[rt],1,n); 47 if(l==r)return ; 48 int mid=(l+r)>>1; 49 merge(lon[o],lon[rt],l,mid); 50 merge(ron[o],ron[rt],mid+1,r); 51 } 52 int query(int o,int rt,int l,int r,int x,int k){ 53 if(l==r)return l; 54 int mid=(l+r)>>1; 55 int now=_query(::rt[lon[o]],::rt[lon[rt]],1,n,x); 56 if(now>=k)return query(lon[o],lon[rt],l,mid,x,k); 57 else return query(ron[o],ron[rt],mid+1,r,x,k-now); 58 } 59 int main(){ 60 scanf("%d%d%d%d",&n,&w,&q,&type); 61 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 62 for(int i=1;i<=n;i++){ 63 v[a[i]].push_back(i); 64 if(v[a[i]].size()>w){ 65 np[v[a[i]][v[a[i]].size()-w-1]]=i; 66 if(v[a[i]].size()>w+1) 67 nnp[v[a[i]][v[a[i]].size()-w-2]]=i; 68 } 69 } 70 for(int i=1;i<=n;i++){ 71 if(!np[i])np[i]=n+1; 72 if(!nnp[i])nnp[i]=n+1; 73 update(root[i],0,n-1,a[i],i,np[i]-1,1); 74 if(np[i]<=n)update(root[i],0,n-1,a[i],np[i],nnp[i]-1,-w); 75 merge(root[i-1],root[i],0,n-1); 76 } 77 int ans=0; 78 for(int t=1,l,r,k,now;t<=q;t++){ 79 scanf("%d%d%d",&l,&r,&k); 80 if(type)l^=ans,r^=ans,k^=ans; 81 now=_query(rt[root[l-1]],rt[root[r]],1,n,r); 82 if(now<k)ans=n; 83 else ans=query(root[l-1],root[r],0,n-1,r,k); 84 printf("%d\n",ans); 85 } 86 return 0; 87 }
T2,容斥來求$\sum_{i=1}^{n}{f_{d}{[n]}}$,咱們設$\lambda{[i]}=f_{\infty}{[i]}$,咱們如今要求的就是
$$F_{d}{[n]}=\sum_{i=1}^{n}{\mu{[i]} \sum_{j=1}^{ \lfloor \frac{n}{i^{d+1}} \rfloor} {\lambda{[i^{d+1} \cdot j ]}} }$$
而後由於$\lambda$是徹底積性函數,因此咱們把關於i的都提到外面,咱們如今還須要求一個$\sum{\lambda}$,而後咱們發現$\lambda \otimes 1 = [x \; is \; Perfect \;Square]$,而後就能夠杜教篩了。
1 #include <bits/stdc++.h> 2 #define N 5005000 3 #define int long long 4 using namespace std; 5 int prime[N/10],tot,n,m,ans; 6 bool vis[N]; 7 int mu[N],lmd[N],slmd[N],phi[N],sphi[N],pw[100500][44]; 8 int f[N],sf[N],tim[N],mx[N]; 9 unordered_map<int,int> hphi,hlmd; 10 void init(){ 11 mu[1]=1;mx[1]=1; 12 lmd[1]=slmd[1]=1; 13 phi[1]=sphi[1]=1; 14 for(int i=2;i<=5000000;i++){ 15 if(!vis[i]){ 16 prime[++tot]=i; 17 phi[i]=i-1;mu[i]=lmd[i]=-1; 18 tim[i]=mx[i]=1; 19 } 20 for(int j=1;j<=tot&&i*prime[j]<=5000000;j++){ 21 vis[i*prime[j]]=1; 22 lmd[i*prime[j]]=-lmd[i]; 23 if(i%prime[j]==0){ 24 tim[i*prime[j]]=tim[i]+1; 25 mx[i*prime[j]]=max(mx[i],tim[i]+1); 26 phi[i*prime[j]]=phi[i]*prime[j]; 27 mu[i*prime[j]]=0; 28 break; 29 } 30 phi[i*prime[j]]=phi[i]*phi[prime[j]]; 31 mu[i*prime[j]]=-mu[i]; 32 tim[i*prime[j]]=1; 33 mx[i*prime[j]]=mx[i]; 34 } 35 sphi[i]=sphi[i-1]+phi[i]; 36 slmd[i]=slmd[i-1]+lmd[i]; 37 } 38 for(int i=1;i<=5000000;i++){ 39 f[i]=lmd[i]*max(0ll,m-mx[i]+1); 40 sf[i]=sf[i-1]+f[i]; 41 } 42 for(int i=1;i<=100000;i++){ 43 pw[i][0]=1; 44 for(int j=1;j<=41;j++){ 45 pw[i][j]=pw[i][j-1]*i; 46 if(pw[i][j]>10000000000ll)break; 47 } 48 } 49 } 50 int getsphi(int n){ 51 if(n<=5000000)return sphi[n]; 52 if(hphi.count(n))return hphi[n]; 53 int ans=1ll*n*(n+1)/2; 54 for(int i=2,j;i<=n;i=j+1){ 55 j=n/(n/i); 56 ans-=(j-i+1)*getsphi(n/i); 57 } 58 return hphi[n]=ans; 59 } 60 int getslmd(int n){ 61 if(n<=5000000)return slmd[n]; 62 if(hlmd.count(n))return hlmd[n]; 63 int ans=sqrt(n); 64 for(int i=2,j;i<=n;i=j+1){ 65 j=n/(n/i); 66 ans-=(j-i+1)*getslmd(n/i); 67 } 68 return hlmd[n]=ans; 69 } 70 int getf(int d,int x){ 71 int ans=0; 72 for(int i=1;pw[i][d+1]&&pw[i][d+1]<=x;i++) 73 ans+=((d&1)?(1):(lmd[i]))*mu[i]*getslmd(x/pw[i][d+1]); 74 return ans; 75 } 76 int getsf(int x){ 77 if(x<=5000000)return sf[x]; 78 int ans=0; 79 for(int d=1;d<=m;d++)ans+=getf(d,x); 80 return ans; 81 } 82 int gcd(int a,int b){return !b?a:gcd(b,a%b);} 83 signed main(){ 84 scanf("%lld%lld",&n,&m); 85 init(); 86 for(int i=1,j,last=0,now;i<=n;i=j+1){ 87 j=n/(n/i); 88 now=getsf(j); 89 ans+=(now-last)*(2*getsphi(n/i)-1); 90 last=now; 91 } 92 printf("%lld\n",ans&1073741823); 93 }
T3,咱們利用指望的線性性,考慮求出每一個點的貢獻,即每一個點的指望通過次數*其對應的距離,咱們考慮如何求出一個狀態下某個點的指望通過次數,由於選點是隨機的,因此咱們只需統記若干1的狀態下0,1的點的指望通過次數,咱們考慮在這一層算下一步形成的貢獻,因而轉移方程就有了。
$$f_{i,0}=\frac{i}{n} f_{i-1,0} + \frac{n-i-1}{n} f_{i+1,0} +\frac{1}{n}(f_{i+1,1}+[notend_{i+1}])$$
$$f_{i,1}=\frac{i-1}{n}f_{i-1,1} +\frac{n-i}{n} f_{i+1,1} +\frac{1}{n}(f_{i-1,0}+[notend_{i-1}])$$
而後咱們知道$f_{0/n,0/1}=0$,咱們在設$f_{1,0}=x,f_{1,1}=y$,而後推到$f_{n-1}$,而後咱們就能夠解二元一次方程組了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define mod 1000000007 7 #define N 100500 8 using namespace std; 9 int n,num1,inv[N],ans; 10 char s[N]; 11 struct data{ 12 int x,y,z; 13 data(){x=y=z=0;} 14 data(int a,int b,int c){x=a;y=b;z=c;} 15 data operator + (data a){return data((x+a.x)%mod,(y+a.y)%mod,(z+a.z)%mod);} 16 data operator - (data a){return data((x-a.x+mod)%mod,(y-a.y+mod)%mod,(z-a.z+mod)%mod);} 17 data operator * (int a){return data(1ll*x*a%mod,1ll*y*a%mod,1ll*z*a%mod);} 18 }f[N][2],one; 19 int qp(int a,int b){ 20 int c=1; 21 for(;b;b>>=1,a=1ll*a*a%mod) 22 if(b&1)c=1ll*c*a%mod; 23 return c; 24 } 25 void UPD(int &a,int b){ 26 a=(a+b>=mod)?(a+b-mod):(a+b); 27 } 28 namespace graph{ 29 int e=1,head[N],d1[N],d2[N],d[N],size[N]; 30 struct edge{ 31 int v,next; 32 }ed[N<<1]; 33 void add(int u,int v){ 34 ed[e].v=v;ed[e].next=head[u]; 35 head[u]=e++; 36 } 37 void dfs1(int x,int f){ 38 size[x]=1; 39 for(int i=head[x];i;i=ed[i].next){ 40 int v=ed[i].v; 41 if(v==f)continue; 42 dfs1(v,x); 43 d1[x]+=d1[v]+size[v]; 44 size[x]+=size[v]; 45 } 46 } 47 void dfs2(int x,int f){ 48 for(int i=head[x];i;i=ed[i].next){ 49 int v=ed[i].v; 50 if(v==f)continue; 51 d2[v]=d2[x]+(d1[x]-d1[v]-size[v])+(n-size[v]); 52 dfs2(v,x); 53 } 54 d[x]=1ll*(d1[x]+d2[x])*inv[n]%mod; 55 } 56 } 57 using namespace graph; 58 int main(){ 59 //freopen("test.in","r",stdin); 60 scanf("%d",&n); 61 scanf("%s",s+1); 62 for(int i=1;i<=n;i++) 63 if(s[i]=='1')num1++; 64 inv[0]=inv[1]=1; 65 for(int i=2,x;i<=n;i++){ 66 scanf("%d",&x); 67 add(x,i);add(i,x); 68 inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod; 69 } 70 dfs1(1,0);dfs2(1,0); 71 72 f[0][0]=data(0,0,0); 73 f[0][1]=data(0,0,0); 74 f[1][0]=data(1,0,0); 75 f[1][1]=data(0,1,0); 76 one=data(0,0,1); 77 78 f[2][1]=(f[1][1]*n)*inv[n-1]; 79 f[2][0]=(f[1][0]*n-f[2][1]-one)*inv[n-2]; 80 for(int i=3;i<n;i++){ 81 f[i][1]=(f[i-1][1]*n-f[i-2][1]*(i-2)-f[i-2][0]-one)*inv[n-i+1]; 82 f[i][0]=(f[i-1][0]*n-f[i-2][0]*(i-1)-f[i][1]-one)*inv[n-i]; 83 } 84 f[n-1][1]=f[n-1][1]*n-f[n-2][1]*(n-2)-f[n-2][0]-(n==2?data(0,0,0):one); 85 f[n-1][0]=f[n-1][0]*n-f[n-2][0]*(n-1); 86 87 //printf("%d %d %d\n",f[n-1][1].x,f[n-1][1].y,f[n-1][1].z); 88 //printf("%d %d %d\n",f[n-1][0].x,f[n-1][0].y,f[n-1][0].z); 89 90 int a1=f[n-1][1].x,b1=f[n-1][1].y,c1=mod-f[n-1][1].z; 91 int a2=f[n-1][0].x,b2=f[n-1][0].y,c2=mod-f[n-1][0].z; 92 int d1=(1ll*c1*a2%mod-1ll*c2*a1%mod+mod)%mod; 93 int d2=(1ll*b1*a2%mod-1ll*b2*a1%mod+mod)%mod; 94 int y=1ll*d1*qp(d2,mod-2)%mod; 95 int x=1ll*(c1-1ll*b1*y%mod+mod)%mod*qp(a1,mod-2)%mod; 96 97 //printf("x==%d y==%d\n",x,y); 98 99 int f0=((1ll*f[num1][0].x*x%mod+1ll*f[num1][0].y*y%mod)%mod+f[num1][0].z)%mod; 100 int f1=((1ll*f[num1][1].x*x%mod+1ll*f[num1][1].y*y%mod)%mod+f[num1][1].z)%mod; 101 102 //printf("f0==%d f1==%d\n",f0,f1); 103 104 for(int i=1;i<=n;i++){ 105 if(s[i]=='0')UPD(ans,1ll*(f0+inv[n])*d[i]%mod); 106 else UPD(ans,1ll*(f1+inv[n])*d[i]%mod); 107 } 108 printf("%d\n",ans); 109 return 0; 110 }
4.26
今天這套題,充分暴露了個人問題,不能怪題,仍是本身弱。
開場先讀題,發現T1計算幾何好像很清真,T2貌似是迴文自動機?T3是DP?而後思考了20minT1,開始寫,寫了1h左右寫完了,而後造了幾組小樣例調了調,而後過不了大樣例,而後開始死磕,而後還有90min時發現後兩題還沒看,而後把暴力都寫上了,接着調,最後一個小時手玩發現樣例好像是錯的,而後就崩潰了。最後看了一眼T3,發現好像是傻逼網絡流,沒時間打了。80+30+20=130 rank7,wq,zzhAK了??T1能夠忽略多邊形???這麼傻逼,T3果真是sb網絡流,T2貌似也是sb題,而後就GG了。後來發現是我重心求錯了,他要求整個面積的重心,而我求的是多邊形的重心。
T1,數據太水了,個人代碼好像也不對。就是大模擬。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 #define eps 1e-8 8 const double pi=acos(-1.0); 9 struct point{ 10 double x,y; 11 point (){x=y=0;} 12 point (double a,double b){x=a;y=b;} 13 point operator + (point a){return point(x+a.x,y+a.y);} 14 point operator - (point a){return point(x-a.x,y-a.y);} 15 double operator * (point a){return x*a.y-y*a.x;} 16 point operator * (double a){return point(x*a,y*a);} 17 point operator / (double a){return point(x/a,y/a);} 18 }sun,ear,g,p[33],np; 19 int n; 20 double t1,t2,t,R,alp,dis,alpl,alpr,pl,pr,ans; 21 double getdis(point a){ 22 return sqrt(a.x*a.x+a.y*a.y); 23 } 24 bool cross1(point a){ 25 for(int i=1;i<=n;i++) 26 if(getdis(p[i]-sun)<=getdis(a-sun)&&(sun-p[i])*(a-p[i])>=0)return 1; 27 return 0; 28 } 29 bool cross2(point a){ 30 for(int i=1;i<=n;i++) 31 if(getdis(p[i]-sun)<=getdis(a-sun)&&(a-p[i])*(sun-p[i])>=0)return 1; 32 return 0; 33 } 34 int main(){ 35 scanf("%lf%lf%lf%lf%lf",&sun.x,&sun.y,&ear.x,&ear.y,&R); 36 scanf("%d%lf%lf%lf",&n,&t1,&t2,&t); 37 for(int i=1;i<=n;i++) 38 scanf("%lf%lf",&p[i].x,&p[i].y); 39 for(int i=1;i<=n;i++){ 40 alp=atan2(p[i].y-ear.y,p[i].x-ear.x); 41 dis=getdis(p[i]-ear); 42 alp=alp+2*pi/t1*t; 43 p[i]=point(ear.x+dis*cos(alp),ear.y+dis*sin(alp)); 44 } 45 double S=0; 46 for(int i=1;i<=n;i++) 47 { 48 double tmp=p[i]*p[i==n?1:i+1]; 49 g=g+((p[i]+p[i==n?1:i+1])*tmp); 50 S+=tmp; 51 } 52 g=g/(3*S); 53 for(int i=1;i<=n;i++){ 54 alp=atan2(p[i].y-g.y,p[i].x-g.x); 55 dis=getdis(p[i]-g); 56 alp=alp+2*pi/t2*t-2*pi/t1*t; 57 p[i]=point(g.x+dis*cos(alp),g.y+dis*sin(alp)); 58 } 59 dis=getdis(ear-sun); 60 dis=sqrt(dis*dis-R*R); 61 alp=atan2(sun.y-ear.y,sun.x-ear.x); 62 double l=0,r=pi,mid; 63 while(l+eps<=r){ 64 mid=(l+r)/2.0; 65 if(getdis(sun-point(ear.x+cos(alp+mid)*R,ear.y+sin(alp+mid)*R))<=dis)l=mid; 66 else r=mid; 67 } 68 alpl=alp-mid;alpr=alp+mid; 69 if(alpr<alpl)alpr+=2*pi; 70 l=alpl,r=alpr; 71 while(l+eps<=r){ 72 mid=(l+r)/2.0; 73 np=point(ear.x+cos(mid)*R,ear.y+sin(mid)*R); 74 if(cross1(np))r=mid; 75 else l=mid; 76 } 77 pl=mid; 78 l=pl,r=alpr; 79 while(l+eps<=r){ 80 mid=(l+r)/2.0; 81 np=point(ear.x+cos(mid)*R,ear.y+sin(mid)*R); 82 if(cross2(np))l=mid; 83 else r=mid; 84 } 85 pr=mid; 86 ans=((alpr-pr)+(pl-alpl))*R; 87 printf("%0.2lf\n",ans); 88 return 0; 89 }
T2,manacher水題。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define mod 1000000007 7 #define N 2000500 8 using namespace std; 9 int T,n,l[N],f[N],g[N],a1[N],b1[N],a2[N],b2[N],tot,ans,now,de; 10 char s[N],s1[N]; 11 void UPD(int &a,int b){ 12 a=(a+b>=mod)?(a+b-mod):(a+b); 13 } 14 void manacher(){ 15 int mx=0,pos=0; 16 for(int i=1;i<=tot;i++){ 17 if(i<mx)l[i]=min(l[2*pos-i],mx-i); 18 else l[i]=0; 19 while(i-l[i]>0&&i+l[i]<=tot&&s1[i-l[i]]==s1[i+l[i]])l[i]++; 20 if(i+l[i]>mx)mx=i+l[i],pos=i; 21 if(i&1){ 22 int posl=(i-l[i]+2)>>1,posr=(i+l[i]-2)>>1,posn=(i+1)>>1; 23 if(posl>posr)continue; 24 UPD(a1[posl],posr);UPD(b1[posl],mod-1); 25 UPD(a1[posn],mod-posn+1);UPD(b1[posn],1); 26 27 UPD(a2[posr],posl);UPD(b2[posr],1); 28 UPD(a2[posn-1],mod-posn);UPD(b2[posn-1],mod-1); 29 } 30 else{ 31 int posl=(i-l[i]+2)>>1,posr=(i+l[i]-2)>>1,posn=i>>1; 32 if(posl>posr)continue; 33 UPD(a1[posl],posr);UPD(b1[posl],mod-1); 34 UPD(a1[posn+1],mod-posn+1);UPD(b1[posn+1],1); 35 36 UPD(a2[posr],posl);UPD(b2[posr],1); 37 UPD(a2[posn-1],mod-posn-1);UPD(b2[posn-1],mod-1); 38 } 39 } 40 } 41 int main(){ 42 //freopen("test.in","r",stdin); 43 scanf("%d",&T); 44 while(T--){ 45 scanf("%s",s+1); 46 n=strlen(s+1); 47 ans=tot=0; 48 memset(a1,0,sizeof a1); 49 memset(b1,0,sizeof b1); 50 memset(a2,0,sizeof a2); 51 memset(b2,0,sizeof b2); 52 s1[++tot]='#'; 53 for(int i=1;i<=n;i++){ 54 s1[++tot]=s[i]; 55 s1[++tot]='#'; 56 } 57 manacher(); 58 now=de=0; 59 for(int i=1;i<=n;i++){ 60 UPD(now,de); 61 UPD(now,a1[i]); 62 UPD(de,b1[i]); 63 f[i]=now; 64 } 65 now=de=0; 66 for(int i=n;i;i--){ 67 UPD(now,de); 68 UPD(now,a2[i]); 69 UPD(de,b2[i]); 70 g[i]=now; 71 } 72 ans=0; 73 for(int i=1;i<n;i++) 74 UPD(ans,1ll*g[i]*f[i+1]%mod); 75 printf("%d\n",ans); 76 } 77 return 0; 78 }
T3,網絡流水題,最大權閉合子圖加上文理分科的思想。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 #define inf 0x3fffffff 8 #define N 150 9 using namespace std; 10 int Tim,n,ans,buc[11],a[11],b[11],c[N],w[N][N]; 11 char s[N]; 12 int e=2,head[N]; 13 struct edge{ 14 int u,v,f,next; 15 }ed[N*N<<2]; 16 void add(int u,int v,int f1,int f2){ 17 ed[e].u=u;ed[e].v=v;ed[e].f=f1; 18 ed[e].next=head[u];head[u]=e++; 19 ed[e].u=v;ed[e].v=u;ed[e].f=f2; 20 ed[e].next=head[v];head[v]=e++; 21 } 22 int dep[N],S,T; 23 bool bfs(){ 24 memset(dep,0,sizeof dep); 25 dep[S]=1; 26 queue<int> q;q.push(S); 27 while(!q.empty()){ 28 int x=q.front();q.pop(); 29 for(int i=head[x];i;i=ed[i].next){ 30 int v=ed[i].v; 31 if(ed[i].f&&!dep[v]){ 32 dep[v]=dep[x]+1; 33 if(v==T)return 1; 34 q.push(v); 35 } 36 } 37 } 38 return 0; 39 } 40 int dfs(int x,int f){ 41 if(x==T||!f)return f; 42 int ans=0; 43 for(int i=head[x];i;i=ed[i].next){ 44 int v=ed[i].v; 45 if(ed[i].v&&dep[v]==dep[x]+1){ 46 int nxt=dfs(v,min(f,ed[i].f)); 47 ans+=nxt;f-=nxt;ed[i].f-=nxt;ed[i^1].f+=nxt; 48 if(!f)break; 49 } 50 } 51 if(!ans)dep[x]=-1; 52 return ans; 53 } 54 int dinic(){ 55 int ans=0; 56 while(bfs())ans+=dfs(S,inf); 57 return ans; 58 } 59 int sum[N]; 60 int main(){ 61 scanf("%d",&Tim); 62 while(Tim--){ 63 scanf("%d",&n);ans=0; 64 scanf("%s",s+1); 65 for(int i=1;i<=n;i++)c[i]=s[i]-'0'; 66 for(int i=0;i<=9;i++) 67 scanf("%d%d",&a[i],&b[i]); 68 memset(sum,0,sizeof sum); 69 for(int i=1;i<=n;i++) 70 for(int j=1;j<=n;j++){ 71 scanf("%d",&w[i][j]); 72 if(i==j)continue; 73 sum[i]+=w[i][j]; 74 sum[j]+=w[i][j]; 75 ans+=2*w[i][j]; 76 } 77 e=2;memset(head,0,sizeof head); 78 S=n+11;T=S+1; 79 for(int i=0;i<=9;i++)add(n+i+1,T,2*(b[i]-a[i]),0); 80 for(int i=1;i<=n;i++){ 81 add(S,i,sum[i],0); 82 add(i,T,2*a[c[i]],0); 83 add(i,n+c[i]+1,inf,0); 84 for(int j=i+1;j<=n;j++) 85 add(i,j,w[i][j]+w[j][i],w[i][j]+w[j][i]); 86 } 87 printf("%d\n",(ans-dinic())/2); 88 } 89 return 0; 90 }
RP上紅,233。
加油吧。
4.27
吸收昨天的教訓,先讀了一遍題,發現T2原題,T1,T3都不會。而後T2換題了,看了看好像是裸插頭。以爲T1是多項式,而後推,推了一個多小時,沒推出來,puts了樣例,而後去把T3的暴力打了,以後去看T2,寫插頭DP,寫完發現看錯數據範圍了。而後過了樣例,沒怎麼檢查,而後去推T1的70分,感受是個dp,仍是沒推出來。而後GG,5+11+30=46 rank6,T2,插頭dp狀況沒討論全掛了24分,T1貌似O(n^4)暴力dp很清真。然而正解是二分圖生成樹。T3分塊。。。
T1,$O(n^{4})$,dp是枚舉一個點所在樹的大小,而後套路組合數轉移。而後咱們發現把奇數層和偶數層當作兩種點,實際上是求徹底二分圖的生成樹個數,這個咱們能夠打表發現答案是$S(n,m)=n^{m-1}+m^{n-1}$,最後$ans=C_{n-1}^{m-1} \cdot S(n-m,m)$
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 int n,m,mod,inv[500500]; 8 int qp(int a,int b){ 9 int c=1; 10 for(;b;b>>=1,a=1ll*a*a%mod) 11 if(b&1)c=1ll*c*a%mod; 12 return c; 13 } 14 int C(int n,int m){ 15 m=min(m,n-m); 16 int ans=1; 17 for(int i=1;i<=m;i++) 18 ans=1ll*ans*(n-i+1)%mod; 19 inv[1]=1; 20 for(int i=2;i<=m;i++){ 21 inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod; 22 ans=1ll*ans*inv[i]%mod; 23 } 24 return ans; 25 } 26 int main(){ 27 scanf("%d%d%d",&n,&m,&mod); 28 printf("%lld\n",1ll*C(n-1,m-1)*qp(m,n-m-1)%mod*qp(n-m,m-1)%mod); 29 return 0; 30 }
T2,35分插頭dp
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define N 35 8 #define inf 0x3fffffff 9 using namespace std; 10 int n,m,num,vis[N][N],c[N][N],d[N][N]; 11 int now,last,mx,my,ans,Tim; 12 struct hash_table{ 13 static const int P=333331; 14 int head[P+10],nxt[P+10],val[P+10],tot,key[P+10]; 15 void clear(){ 16 memset(head,0,sizeof head); 17 tot=0; 18 } 19 void add(int x,int v){ 20 int y=x%P; 21 nxt[++tot]=head[y];head[y]=tot; 22 key[tot]=x;val[tot]=v; 23 } 24 int & operator [] (int x){ 25 int y=x%P; 26 for(int i=head[y];i;i=nxt[i]) 27 if(key[i]==x)return val[i]; 28 add(x,-inf); 29 return val[tot]; 30 } 31 }f[2]; 32 int gets(int x,int y){ 33 return ((x>>((y-1)*2))&3); 34 } 35 int find(int x,int y){ 36 for(int i=y,cnt=0,now,pos=(gets(x,y)==1?1:-1);;i+=pos){ 37 now=gets(x,i); 38 if(now==1)cnt++; 39 if(now==2)cnt--; 40 if(!cnt)return i; 41 } 42 } 43 void change(int &x,int y,int z){ 44 x^=(gets(x,y)<<(2*(y-1)))^(z<<(2*(y-1))); 45 } 46 void dp(int i,int j){ 47 swap(now,last); 48 f[now].clear(); 49 for(int k=1;k<=f[last].tot;k++){ 50 int nf=f[last].val[k],s=f[last].key[k]; 51 int x=gets(s,j),y=gets(s,j+1); 52 if(x==1&&y==2){ 53 change(s,j,0);change(s,j+1,0); 54 if((!s)&&(i>mx||(i==mx&&j>=my))) 55 ans=max(ans,nf); 56 f[now][s]=max(f[now][s],nf); 57 } 58 else if(x==2&&y==1){ 59 change(s,j,0);change(s,j+1,0); 60 f[now][s]=max(f[now][s],nf); 61 } 62 else if(x==1&&y==1){ 63 change(s,find(s,j+1),1); 64 change(s,j,0);change(s,j+1,0); 65 f[now][s]=max(f[now][s],nf); 66 } 67 else if(x==2&&y==2){ 68 change(s,find(s,j),2); 69 change(s,j,0);change(s,j+1,0); 70 f[now][s]=max(f[now][s],nf); 71 } 72 else if(!x&&!y){ 73 if(!vis[i][j])f[now][s]=max(f[now][s],nf); 74 if(i==n||j==m)continue; 75 change(s,j,1);change(s,j+1,2); 76 f[now][s]=max(f[now][s],nf+c[i][j]+d[i][j]); 77 } 78 else if(x&&!y){ 79 if(i==n)continue; 80 f[now][s]=max(f[now][s],nf+d[i][j]); 81 } 82 else if(!x&&y){ 83 if(j==m)continue; 84 f[now][s]=max(f[now][s],nf+c[i][j]); 85 } 86 } 87 } 88 int main(){ 89 //freopen("bounce5d.in","r",stdin); 90 //freopen("1.out","w",stdout); 91 scanf("%d",&Tim); 92 while(Tim--){ 93 scanf("%d%d",&n,&m); 94 //if(n>10&&m>10){puts("0");continue;} 95 if(n>=m){ 96 for(int i=1;i<=n;i++) 97 for(int j=1;j<m;j++) 98 scanf("%d",&c[i][j]); 99 for(int i=1;i<n;i++) 100 for(int j=1;j<=m;j++) 101 scanf("%d",&d[i][j]); 102 memset(vis,0,sizeof vis); 103 scanf("%d",&num); 104 mx=my=0; 105 for(int i=1,x,y;i<=num;i++){ 106 scanf("%d%d",&x,&y); 107 vis[x][y]=1; 108 if(x>mx)mx=x,my=y; 109 else if(x==mx&&y>my)my=y; 110 } 111 } 112 else{ 113 swap(n,m); 114 for(int j=1;j<=m;j++) 115 for(int i=1;i<n;i++) 116 scanf("%d",&d[i][j]); 117 for(int j=1;j<m;j++) 118 for(int i=1;i<=n;i++) 119 scanf("%d",&c[i][j]); 120 memset(vis,0,sizeof vis); 121 scanf("%d",&num); 122 mx=my=0; 123 for(int i=1,x,y;i<=num;i++){ 124 scanf("%d%d",&y,&x); 125 vis[x][y]=1; 126 if(x>mx)mx=x,my=y; 127 else if(x==mx&&y>my)my=y; 128 } 129 } 130 now=1,last=0,ans=-inf; 131 if(!num)ans=0; 132 f[now].clear(); 133 f[now][0]=0; 134 for(int i=1;i<=n;i++){ 135 for(int j=1;j<=m;j++) 136 dp(i,j); 137 swap(now,last); 138 f[now].clear(); 139 for(int k=1;k<=f[last].tot;k++) 140 f[now][f[last].key[k]<<2]=max(f[now][f[last].key[k]<<2],f[last].val[k]); 141 } 142 if(ans==-inf)puts("Impossible"); 143 else printf("%d\n",ans); 144 } 145 }
正解網絡流,其實仍是套路,咱們把每一個點拆點,而後本身流一條S->x1->x2->T,而後黑白染色,分別是橫進豎出,豎進橫出,若是x能夠到y,那麼x1->y2連一條邊,這樣x2也須要一個流量,y1也須要出一個流量,就能夠跑最小費用最大流了。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define N 33 6 #define inf 0x3fffffff 7 using namespace std; 8 int n,m,num,vis[N][N],c[N][N],d[N][N],Tim; 9 int e,head[N*N<<1]; 10 struct edge{ 11 int u,v,w,f,next; 12 }ed[(N*N)<<4]; 13 void add(int u,int v,int f,int w){ 14 ed[e].u=u;ed[e].v=v;ed[e].f=f;ed[e].w=w; 15 ed[e].next=head[u];head[u]=e++; 16 ed[e].u=v;ed[e].v=u;ed[e].f=0;ed[e].w=-w; 17 ed[e].next=head[v];head[v]=e++; 18 } 19 #define id(i,j) (((i)-1)*2+(j)) 20 int dis[N*N<<1],Flow,Cost,S,T,id[N][N],tot1,tot2; 21 int bo[N*N<<1],tim; 22 int q[N*N*N],he,ta; 23 bool spfa(){ 24 memset(dis,-0x3f,sizeof dis); 25 tim++;dis[S]=0; 26 he=ta=1;q[1]=S; 27 while(he<=ta){ 28 int x=q[he++];bo[x]=0; 29 for(int i=head[x];i;i=ed[i].next){ 30 int v=ed[i].v; 31 if(ed[i].f&&dis[v]<dis[x]+ed[i].w){ 32 dis[v]=dis[x]+ed[i].w; 33 if(bo[v]!=tim){bo[v]=tim;q[++ta]=v;} 34 } 35 } 36 } 37 return dis[T]!=dis[0]; 38 } 39 int dfs(int x,int f){ 40 bo[x]=tim; 41 if(x==T){ 42 Cost+=dis[T]*f; 43 Flow+=f; 44 return f; 45 } 46 if(!f)return 0; 47 int ans=0; 48 for(int i=head[x];i;i=ed[i].next){ 49 int v=ed[i].v; 50 if(ed[i].f&&dis[v]==dis[x]+ed[i].w&&bo[v]!=tim){ 51 int nxt=dfs(v,min(f,ed[i].f)); 52 ans+=nxt;f-=nxt;ed[i].f-=nxt;ed[i^1].f+=nxt; 53 if(!f)break; 54 } 55 } 56 return ans; 57 } 58 void work(){ 59 Cost=Flow=0; 60 while(spfa()){ 61 do{ 62 tim++; 63 dfs(S,inf); 64 }while(bo[T]==tim); 65 } 66 if(Flow!=n*m)puts("Impossible"); 67 else printf("%d\n",Cost); 68 return ; 69 } 70 int main(){ 71 //freopen("bounce6e.in","r",stdin); 72 //freopen("4.out","w",stdout); 73 scanf("%d",&Tim); 74 while(Tim--){ 75 scanf("%d%d",&n,&m); 76 for(int i=1;i<=n;i++) 77 for(int j=1;j<m;j++) 78 scanf("%d",&c[i][j]); 79 for(int i=1;i<n;i++) 80 for(int j=1;j<=m;j++) 81 scanf("%d",&d[i][j]); 82 scanf("%d",&num); 83 memset(vis,0,sizeof vis); 84 for(int i=1,x,y;i<=num;i++){ 85 scanf("%d%d",&x,&y); 86 vis[x][y]=1; 87 } 88 tot1=tot2=0; 89 for(int i=1;i<=n;i++){ 90 for(int j=1;j<=m;j++){ 91 if((i+j)&1)id[i][j]=++tot1; 92 else id[i][j]=++tot2; 93 } 94 } 95 for(int i=1;i<=n;i++) 96 for(int j=1;j<=m;j++) 97 if(!((i+j)&1))id[i][j]+=tot1; 98 S=n*m*2+1;T=S+1; 99 e=2,memset(head,0,sizeof head); 100 for(int i=1;i<=n;i++){ 101 for(int j=1;j<m;j++){ 102 if((i+j)&1)add(id(id[i][j],1),id(id[i][j+1],2),1,c[i][j]); 103 else add(id(id[i][j+1],1),id(id[i][j],2),1,c[i][j]); 104 } 105 } 106 for(int i=1;i<n;i++){ 107 for(int j=1;j<=m;j++){ 108 if((i+j)&1)add(id(id[i+1][j],1),id(id[i][j],2),1,d[i][j]); 109 else add(id(id[i][j],1),id(id[i+1][j],2),1,d[i][j]); 110 } 111 } 112 for(int i=1;i<=n;i++){ 113 for(int j=1;j<=m;j++){ 114 add(S,id(id[i][j],1),1,0); 115 add(id(id[i][j],2),T,1,0); 116 if(!vis[i][j])add(id(id[i][j],1),id(id[i][j],2),1,0); 117 } 118 } 119 work(); 120 } 121 }
T3,分塊,咱們發現權值範圍很小,而後分塊時要保證每一個塊的權值範圍不超過$len*sqrt{n}$,而後每$\sqrt{m}$次操做暴力重構。
感受根號的思路都很巧妙,放到數列上就是分塊莫隊之類的,腦洞很大,思路清奇。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define N 100500 8 using namespace std; 9 int e=1,head[N]; 10 struct edge{ 11 int u,v,w,next; 12 }ed[N]; 13 void add(int u,int v,int w){ 14 ed[e].u=u;ed[e].v=v;ed[e].w=w; 15 ed[e].next=head[u];head[u]=e++; 16 } 17 int a[N],tot,L[N],R[N],cnt,be[N],fro[N],en[N]; 18 int minn[705],maxn[705],buc[705][5050],Low,High,mx,mn; 19 int n,m,len,nn,mm,lazy[705]; 20 void dfs(int x,int dep){ 21 a[++tot]=dep; 22 L[x]=tot; 23 for(int i=head[x];i;i=ed[i].next) 24 dfs(ed[i].v,dep+ed[i].w); 25 R[x]=tot; 26 } 27 void build(){ 28 if(cnt){ 29 for(int i=1;i<=cnt;i++){ 30 for(int j=0;j<=maxn[i]-minn[i];j++) 31 buc[i][j]=0; 32 for(int j=fro[i];j<=en[i];j++) 33 a[j]+=lazy[i]; 34 lazy[i]=0; 35 } 36 cnt=0; 37 } 38 mx=mn=a[1];be[1]=++cnt;fro[cnt]=1; 39 for(int i=2;i<=n;i++){ 40 if(i-fro[cnt]>nn||max(mx,a[i])-min(mn,a[i])>nn*len){ 41 maxn[cnt]=mx;minn[cnt]=mn; 42 en[cnt]=i-1;fro[++cnt]=i; 43 be[i]=cnt;mx=mn=a[i]; 44 } 45 else{ 46 be[i]=cnt; 47 mx=max(mx,a[i]); 48 mn=min(mn,a[i]); 49 } 50 } 51 en[cnt]=n;maxn[cnt]=mx;minn[cnt]=mn; 52 Low=100000000;High=0; 53 //cerr<<cnt<<endl; 54 for(int i=1;i<=cnt;i++){ 55 for(int j=fro[i];j<=en[i];j++) 56 buc[i][a[j]-minn[i]]++; 57 for(int j=1;j<=maxn[i]-minn[i];j++) 58 buc[i][j]+=buc[i][j-1]; 59 Low=min(Low,minn[i]); 60 High=max(High,maxn[i]); 61 } 62 } 63 void change(int x){ 64 for(int i=0;i<=maxn[x]-minn[x];i++)buc[x][i]=0; 65 minn[x]=100000000;maxn[x]=0; 66 for(int i=fro[x];i<=en[x];i++){ 67 a[i]+=lazy[x]; 68 maxn[x]=max(maxn[x],a[i]); 69 minn[x]=min(minn[x],a[i]); 70 } 71 lazy[x]=0; 72 for(int i=fro[x];i<=en[x];i++) 73 buc[x][a[i]-minn[x]]++; 74 for(int i=1;i<=maxn[x]-minn[x];i++) 75 buc[x][i]+=buc[x][i-1]; 76 } 77 bool check(int l,int r,int x,int y){ 78 int ans=0; 79 if(be[l]==be[r]){ 80 for(int i=l;i<=r;i++)if(a[i]+lazy[be[l]]<=x)ans++; 81 } 82 else{ 83 for(int i=l;i<=en[be[l]];i++)if(a[i]+lazy[be[l]]<=x)ans++; 84 for(int i=fro[be[r]];i<=r;i++)if(a[i]+lazy[be[r]]<=x)ans++; 85 for(int i=be[l]+1;i<be[r];i++){ 86 if(minn[i]+lazy[i]<=x&&maxn[i]+lazy[i]>=x) 87 ans+=buc[i][x-lazy[i]-minn[i]]; 88 else if(maxn[i]+lazy[i]<x)ans+=buc[i][maxn[i]-minn[i]]; 89 } 90 } 91 return ans>=y; 92 } 93 int query(int l,int r,int y){ 94 int low=Low,high=High,mid,fin=low-1; 95 while(low<=high){ 96 mid=(low+high)>>1; 97 if(check(l,r,mid,y))fin=mid,high=mid-1; 98 else low=mid+1; 99 } 100 return fin; 101 } 102 int main(){ 103 scanf("%d%d%d",&n,&m,&len); 104 nn=250;mm=500; 105 for(int i=2,x,y;i<=n;i++){ 106 scanf("%d%d",&x,&y); 107 add(x,i,y); 108 } 109 dfs(1,0); 110 build(); 111 int o,x,y,l,r,tim=0; 112 while(m--){ 113 scanf("%d%d%d",&o,&x,&y); 114 if(o==1){ 115 l=L[x];r=R[x]; 116 if(r-l+1<y){puts("-1");continue;} 117 printf("%d\n",query(l,r,y)); 118 } 119 else{ 120 l=L[x];r=R[x]; 121 if(be[l]==be[r]){ 122 for(int i=l;i<=r;i++)a[i]+=y; 123 change(be[l]); 124 } 125 else{ 126 for(int i=be[l]+1;i<be[r];i++)lazy[i]+=y; 127 for(int i=l;i<=en[be[l]];i++)a[i]+=y; 128 for(int i=fro[be[r]];i<=r;i++)a[i]+=y; 129 change(be[l]);change(be[r]); 130 } 131 High+=y; 132 tim++; 133 } 134 if(tim==mm){ 135 tim=0; 136 build(); 137 } 138 } 139 return 0; 140 }
翻翻翻!
4.28
先看T1,感受就很水,先寫了個O(n^2)dp,而後觀察推理了一波,發現了個規律,而後打上了。看T2,好像作過相似的,推了一會式子,沒推出來,先寫了30分暴力,而後發現50分好像也能夠作,而後改了改,以後去看T3,一眼只會20分暴力,推了一下,發現a,b串字符集不相交時就是裸的矩陣乘,而後碼碼碼,把兩個部分分都寫上了,懶得拍了,最後發現T2貌似能夠亂dp一波,可是沒時間了,肉眼查了波錯就交了。100+30+60=190 rank3。T2掛分了。炸內存了,md,還沒開long long,這還有分,老天有眼啊。裸暴力210,可是最高分205,落實暴力不掛分看來的確是很重要的。
T1,水題。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <map> 7 #define inf 0x3fffffff 8 #define int long long 9 using namespace std; 10 int pw[105]; 11 map<int,int> mm; 12 int getf(int x){ 13 if(mm.count(x+1))return 0; 14 int ans=0; 15 int pos=upper_bound(pw,pw+61,x)-pw-1; 16 for(int i=pos;~i;i--){ 17 if(pw[i]<=x){ 18 ans++; 19 x-=pw[i]; 20 } 21 if(mm.count(x+1))return ans; 22 } 23 return ans; 24 } 25 int n,m,ans,p[15],vis1,visn; 26 signed main(){ 27 //freopen("2.out","w",stdout); 28 for(int i=0,now=1;i<=60;i++,now=2ll*now){ 29 pw[i]=now; 30 mm[now]=1; 31 } 32 scanf("%lld%lld",&n,&m); 33 for(int i=1;i<=m;i++){ 34 scanf("%lld",&p[i]); 35 if(p[i]==1)vis1=1; 36 if(p[i]==n)visn=1; 37 } 38 if(!vis1)p[++m]=1,ans++; 39 if(!visn&&n!=1)p[++m]=n,ans++; 40 sort(p+1,p+m+1); 41 for(int i=2;i<=m;i++) 42 ans+=getf(p[i]-p[i-1]-1); 43 printf("%lld\n",ans); 44 return 0; 45 }
T2,咱們考慮優化暴力dp,咱們發現函數值是一個下凸的函數,並且總拐點是O(n)級別的,咱們考慮在拐點處維護斜率的增量,這個能夠用一個可並堆來實現。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 200050 5 #define LL long long 6 using namespace std; 7 int n,T; 8 int e,head[N]; 9 struct edge{ 10 int u,v,w,next; 11 }ed[N<<1]; 12 void add(int u,int v,int w){ 13 ed[e].u=u;ed[e].v=v;ed[e].w=w; 14 ed[e].next=head[u];head[u]=e++; 15 } 16 LL f[N]; 17 struct diui{ 18 diui *ch[2]; 19 int x,val; 20 diui(int a,int b){ 21 x=a;val=b; 22 ch[0]=ch[1]=NULL; 23 } 24 }*root[N]; 25 diui *merge(diui *a,diui *b){ 26 if(!a)return b; 27 if(!b)return a; 28 if((a->x>b->x)||(a->x==b->x&&a->val>b->val))swap(a,b); 29 a->ch[1]=merge(a->ch[1],b); 30 swap(a->ch[0],a->ch[1]); 31 return a; 32 } 33 void dfs(int x,int fa,int w){ 34 for(int i=head[x];i;i=ed[i].next){ 35 int v=ed[i].v; 36 if(v==fa)continue; 37 dfs(v,x,ed[i].w); 38 } 39 root[x]=merge(new diui(1,-1),new diui(w,2)); 40 f[x]=w-1; 41 for(int i=head[x];i;i=ed[i].next){ 42 int v=ed[i].v; 43 if(v==fa)continue; 44 root[x]=merge(root[x],root[v]); 45 f[x]+=f[v]; 46 } 47 int p=1,v=0,np,nv; 48 while(1){ 49 np=root[x]->x;nv=root[x]->val; 50 f[x]+=1ll*(np-p)*v;p=np;v+=nv; 51 root[x]=merge(root[x]->ch[0],root[x]->ch[1]); 52 if(v>=0){root[x]=merge(root[x],new diui(np,v));break;} 53 } 54 } 55 int main(){ 56 scanf("%d",&T); 57 while(T--){ 58 scanf("%d",&n); 59 e=1;memset(head,0,sizeof head); 60 for(int i=1,u,v,w;i<n;i++){ 61 scanf("%d%d%d",&u,&v,&w); 62 add(u,v,w);add(v,u,w); 63 } 64 dfs(1,0,1); 65 printf("%lld\n",f[1]); 66 } 67 return 0; 68 }
T3,很好的sam矩乘的題,咱們發現字符集有交時可能一個串會被統計屢次,因而咱們考慮用一種定義方法使得其惟一對應一種狀態,因而咱們設$f_{i,sa,sb}$表示長度爲i的串,被分紅aba...aba這種的最後一個a的子串最短的分割方法其對應在a串的sam中的結點,sb同理,而後轉移也很巧妙,不過這裏地方過小,寫不下。並且這樣的狀態數最可能是8n左右,而後矩乘就能夠。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 #define N 25 8 #define mod 1000000007 9 #define pr pair<int,int> 10 #define mk make_pair 11 #define fi first 12 #define se second 13 using namespace std; 14 int n,m,len,mm[N<<1][N<<1],tot,T,ml; 15 pr p[405];queue<pr> q; 16 char sa[N],sb[N]; 17 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 18 struct sam{ 19 int last,tot,mx[N<<1],ch[N<<1][4],par[N<<1]; 20 void add(int c){ 21 int p=last,np=++tot; 22 mx[np]=mx[p]+1; 23 for(;!ch[p][c];p=par[p])ch[p][c]=np; 24 if(!p)par[np]=1; 25 else{ 26 int q=ch[p][c]; 27 if(mx[q]==mx[p]+1)par[np]=q; 28 else{ 29 int nq=++tot; 30 mx[nq]=mx[p]+1;par[nq]=par[q]; 31 memcpy(ch[nq],ch[q],sizeof ch[nq]); 32 par[q]=par[np]=nq; 33 for(;p&&ch[p][c]==q;p=par[p])ch[p][c]=nq; 34 } 35 } 36 last=np; 37 } 38 }sama,samb; 39 struct mart{ 40 int a[155][155]; 41 mart(){memset(a,0,sizeof a);} 42 mart operator *(const mart & B)const{ 43 mart C; 44 for(int i=1;i<=ml;i++) 45 for(int j=1;j<=ml;j++)if(a[i][j]) 46 for(int k=1;k<=ml;k++)if(B.a[j][k]) 47 UPD(C.a[i][k],1ll*a[i][j]*B.a[j][k]%mod); 48 return C; 49 } 50 }A,B; 51 mart qp(mart a,int b){ 52 mart c; 53 for(int i=1;i<=ml;i++) 54 c.a[i][i]=1; 55 for(;b;b>>=1,a=a*a) 56 if(b&1)c=c*a; 57 return c; 58 } 59 void work(){ 60 memset(mm,0,sizeof mm); 61 memset(A.a,0,sizeof A.a); 62 memset(B.a,0,sizeof B.a); 63 for(int i=0;i<4;i++)if(sama.ch[1][i]){ 64 mm[sama.ch[1][i]][0]=++tot; 65 p[tot]=mk(sama.ch[1][i],0),q.push(p[tot]); 66 B.a[1][tot]=1; 67 } 68 while(!q.empty()){ 69 pr now=q.front();q.pop(); 70 int x=now.fi,y=now.se,nx,ny; 71 for(int i=0;i<4;i++){ 72 if(!sama.ch[1][i]&&!samb.ch[1][i])nx=0,ny=0; 73 else if(sama.ch[1][i]&&!samb.ch[1][i]){ 74 if(y==0)nx=sama.ch[x][i],ny=0; 75 else nx=sama.ch[1][i],ny=0; 76 } 77 else if(!sama.ch[1][i]&&samb.ch[1][i]){ 78 if(x==0)nx=0,ny=samb.ch[y][i]; 79 else nx=0,ny=samb.ch[1][i]; 80 } 81 else{ 82 if(x&&y)nx=sama.ch[1][i],ny=samb.ch[1][i]; 83 else if(!x&&y)nx=sama.ch[1][i],ny=samb.ch[y][i]; 84 else if(x&&!y)nx=sama.ch[x][i],ny=samb.ch[1][i]; 85 else nx=sama.ch[1][i],ny=samb.ch[1][i]; 86 } 87 if(!nx&&!ny)continue; 88 if(!mm[nx][ny])mm[nx][ny]=++tot,p[tot]=mk(nx,ny),q.push(p[tot]); 89 A.a[mm[x][y]][mm[nx][ny]]++; 90 } 91 } 92 ml=tot+1; 93 A.a[ml][ml]=1; 94 for(int i=1;i<=tot;i++) 95 if(p[i].se!=0)A.a[i][ml]++; 96 B=B*qp(A,len); 97 printf("%d\n",B.a[1][ml]); 98 } 99 int main(){ 100 scanf("%d",&T); 101 while(T--){ 102 scanf("%d%d%d",&n,&m,&len); 103 scanf("%s",sa+1); 104 sama.last=sama.tot=1; 105 memset(sama.ch,0,sizeof sama.ch); 106 for(int i=1;i<=n;i++){ 107 if(sa[i]=='A')sa[i]='0'; 108 if(sa[i]=='T')sa[i]='1'; 109 if(sa[i]=='C')sa[i]='2'; 110 if(sa[i]=='G')sa[i]='3'; 111 sama.add(sa[i]-'0'); 112 } 113 scanf("%s",sb+1); 114 samb.last=samb.tot=1; 115 memset(samb.ch,0,sizeof samb.ch); 116 for(int i=1;i<=m;i++){ 117 if(sb[i]=='A')sb[i]='0'; 118 if(sb[i]=='T')sb[i]='1'; 119 if(sb[i]=='C')sb[i]='2'; 120 if(sb[i]=='G')sb[i]='3'; 121 samb.add(sb[i]-'0'); 122 } 123 work(); 124 } 125 return 0; 126 }
fighting!fighting!
4.29
先讀了一遍題,發現T1若是不是分數的話就是sb題,而後感受分數也不是很難搞,T2一臉不可作,T3貌似50分是送的?而後開始想T1,感受正解應該是什麼單調隊列優化dp之類的,可是推了一會也沒推出來,而後想了個騙分,就是二分答案,對最後分出來的答案在序列上跑一遍卡個邊界就能夠了,而後寫完了,造了幾組數據調了調eps,然而T2的10分暴力仍是不想寫,就去看T3,先寫了50分暴力,而後想正解,感受是網絡流?yy了一堆建圖都失敗了。以後又去想T1,亂搞出來了個$O(n^{2})$dp,然而怎麼也不能優化。最後把T2的10分暴力打了就完了。100+10+50=160rank2
T1,騙分是正解?就是二分答案,而後對於最後的答案咱們能夠暴力找分數和他匹配,也能夠像我再在序列上跑一遍。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define eps 1e-7 7 #define N 100500 8 #define ld long double 9 using namespace std; 10 int T,n;ld mx,mn; 11 bool vis1[N],vis2[N]; 12 struct data{ 13 ld l,r; 14 bool operator < (const data &a)const{return l<a.l;} 15 }d[N]; 16 bool check(ld x){ 17 ld now=mn; 18 for(int i=1;i<=n;i++){ 19 now=max(now,d[i].l);now+=x; 20 if(now>d[i].r)return 0; 21 } 22 return 1; 23 } 24 int gcd(int a,int b){return !b?a:gcd(b,a%b);} 25 struct fra{ 26 int son,mom; 27 fra(int a,int b){int g=gcd(a,b);son=a/g;mom=b/g;} 28 fra(){son=0,mom=1;} 29 bool operator < (const fra & a)const{return 1ll*son*a.mom<1ll*mom*a.son;} 30 void print(){printf("%d/%d\n",son,mom);} 31 }; 32 int main(){ 33 scanf("%d",&T); 34 while(T--){ 35 scanf("%d",&n); 36 mn=1e9,mx=0; 37 for(int i=1;i<=n;i++){cin>>d[i].l>>d[i].r;mn=min(mn,d[i].l);mx=max(mx,d[i].r);} 38 sort(d+1,d+n+1); 39 ld l=0,r=(mx-mn)/1.0/n,mid,e=1e-12; 40 while(l+e<=r){ 41 mid=(l+r)/2.0; 42 if(check(mid))l=mid; 43 else r=mid; 44 } 45 ld now=mn; 46 memset(vis1,0,sizeof vis1); 47 memset(vis2,0,sizeof vis2); 48 for(int i=1;i<=n;i++,now+=l){ 49 if(now<=d[i].l+eps)vis1[i]=1,now=d[i].l; 50 if(now+l>=d[i].r-eps)vis2[i]=1; 51 } 52 fra ans=fra(1000000000,1); 53 for(int i=1,pos;i<=n;i++){ 54 if(vis1[i])pos=i; 55 if(vis2[i])ans=min(ans,fra(round(d[i].r-d[pos].l),i-pos+1)); 56 } 57 ans.print(); 58 } 59 return 0; 60 }
T2,挺好的一道數學題。
60分dp就是定義f[i][j]表示i個點中有j棵樹的方案數,而後
$$f[i][j]= \frac{1}{j} \sum_{k=1}^{i}{f[i-k][j-1] \cdot k^{k-2} \cdot C_{i}^{k}}$$
套路轉移便可。
1 #pragma GCC optimize ("O3") 2 #include <bits/stdc++.h> 3 #define N 1050 4 #define mod 998244353 5 using namespace std; 6 int qp(int a,int b){ 7 int c=1; 8 for(;b;b>>=1,a=1ll*a*a%mod) 9 if(b&1)c=1ll*c*a%mod; 10 return c; 11 } 12 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 13 int n,m,C[N][N],g[N],f[N][N],inv[N],ans,gc[N]; 14 int main(){ 15 //freopen("test.in","r",stdin); 16 register int i,j,k; 17 scanf("%d%d",&n,&m); 18 for(i=0;i<=n;++i){ 19 C[i][0]=1; 20 for(j=1;j<=i;++j) 21 C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; 22 } 23 g[1]=1; 24 for(i=2;i<=n;++i)g[i]=qp(i,i-2); 25 inv[0]=inv[1]=1; 26 for(i=2;i<=n;++i)inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod; 27 f[0][0]=1; 28 for(i=1;i<=n;++i){ 29 for(k=1;k<=i;++k)gc[k]=1ll*g[k]*C[i][k]%mod; 30 for(j=1;j<=i;++j){ 31 for(k=1;k<=i-j+1;++k) 32 UPD(f[i][j],1ll*f[i-k][j-1]*gc[k]%mod); 33 f[i][j]=1ll*f[i][j]*inv[j]%mod; 34 UPD(f[i][0],mod-f[i][j]); 35 } 36 UPD(f[i][0],qp(2,1ll*i*(i-1)/2%(mod-1))); 37 } 38 for(i=1;i<=n;++i) 39 UPD(ans,1ll*f[n][i]*qp(i,m)%mod); 40 printf("%d\n",ans); 41 return 0; 42 }
正解更nb,由第二類斯特林數可得$x^{k}= \sum_{i=1}^{min(x,k)}{S(k,i) \cdot C_{x}^{i} \cdot i!}$,而後咱們考慮每i個樹聯通塊,他的貢獻就是他在全部方案中出現的次數乘上$S(k,i) \cdot i!$,而後咱們就只需dp出i個點構成j棵樹的方案數就能夠了,這裏的j<=k。注意上面60分的f中i個點中除了j棵樹,還可能有不是樹的聯通塊,而這裏必須只有j棵樹,轉移相似
$$f[i][j]= \sum_{k=1}^{i}{f[i-k][j-1] \cdot k^{k-2} \cdot C_{i-1}^{k-1}}$$
以後把組合數拆開,而後用fft優化便可。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 33333 7 #define mod 998244353 8 using namespace std; 9 int n,m,up,g[N],h[N],ans,len,rev[N<<1]; 10 int fac[N],inv[N],S[25][25],f[25][N<<1],a[N<<1],b[N<<1]; 11 int qp(int a,int b){ 12 int c=1; 13 for(;b;b>>=1,a=1ll*a*a%mod) 14 if(b&1)c=1ll*c*a%mod; 15 return c; 16 } 17 int C(int n,int m){ 18 if(m==0||m==n)return 1; 19 return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod; 20 } 21 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 22 void ntt(int *a,int o){ 23 register int i,j,k,dan,now,t; 24 for(i=0;i<len;i++)if(i<rev[i])swap(a[i],a[rev[i]]); 25 for(k=2;k<=len;k<<=1){ 26 dan=qp(3,(o==1)?((mod-1)/k):(mod-1-(mod-1)/k)); 27 for(i=0;i<len;i+=k){ 28 now=1; 29 for(j=0;j<(k>>1);j++,now=1ll*now*dan%mod){ 30 t=1ll*a[i+j+(k>>1)]*now%mod; 31 a[i+j+(k>>1)]=(a[i+j]-t+mod)%mod; 32 a[i+j]=(a[i+j]+t)%mod; 33 } 34 } 35 } 36 if(o==-1){ 37 int ny=qp(len,mod-2); 38 for(i=0;i<len;i++)a[i]=1ll*a[i]*ny%mod; 39 } 40 } 41 int main(){ 42 scanf("%d%d",&n,&m); 43 up=min(n,m); 44 for(int i=0;i<=m;i++){ 45 S[i][0]=0;S[i][i]=1; 46 for(int j=1;j<i;j++) 47 S[i][j]=(S[i-1][j-1]+1ll*S[i-1][j]*j%mod)%mod; 48 } 49 fac[0]=1;for(int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mod; 50 inv[n]=qp(fac[n],mod-2);for(int i=n;i;i--)inv[i-1]=1ll*inv[i]*i%mod; 51 g[1]=1;for(int i=2;i<=n;i++)g[i]=qp(i,i-2); 52 h[0]=1;for(int i=1;i<=n;i++)h[i]=qp(2,1ll*i*(i-1)/2%(mod-1)); 53 for(len=1;len<=2*n;len<<=1); 54 for(int i=0;i<len;i++){ 55 if(i&1)rev[i]=(rev[i>>1]>>1)|(len>>1); 56 else rev[i]=rev[i>>1]>>1; 57 } 58 f[0][0]=1; 59 for(int i=1;i<=up;i++){ 60 for(int j=1;j<=n;j++)b[j]=1ll*g[j]*inv[j-1]%mod; 61 for(int j=0;j<=n;j++)a[j]=1ll*f[i-1][j]*inv[j]%mod; 62 for(int j=n+1;j<len;j++)b[j]=a[j]=0;b[0]=0; 63 ntt(a,1);ntt(b,1); 64 for(int j=0;j<len;j++)f[i][j]=1ll*a[j]*b[j]%mod; 65 ntt(f[i],-1); 66 for(int j=1;j<=n;j++)f[i][j]=1ll*f[i][j]*fac[j-1]%mod; 67 } 68 for(int i=1,cnt;i<=up;i++){ 69 cnt=0; 70 for(int j=1;j<=n;j++) 71 UPD(cnt,1ll*f[i][j]*C(n,j)%mod*h[n-j]%mod); 72 UPD(ans,1ll*cnt*S[m][i]%mod*fac[i]%mod); 73 } 74 printf("%d\n",ans); 75 return 0; 76 }
T3,sbDP題,f[i][j][k]表示先後各放了i個數,前面i個有j個p,後面有k個p的最優解,而後咱們能夠發現,這樣就能夠避免重複,由於長度爲i和n-i的條件咱們能夠一併考慮。而後就沒了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define P 9705276 7 #define Q 12805858 8 #define N 205 9 #define pr pair<int,int> 10 #define mk make_pair 11 #define LL long long 12 using namespace std; 13 LL read(){ 14 LL a=0;char ch=getchar(); 15 while(ch<'0'||ch>'9')ch=getchar(); 16 while((ch>='0'&&ch<='9')||(ch=='.')) 17 {if(ch!='.')a=a*10+(ch^48);ch=getchar();} 18 return a; 19 } 20 int mm[N<<1][N<<1];LL mx; 21 int Tim,ans,len,nump,numq,n,f[N][N][N],ansj,ansk; 22 pr pre[N][N][N]; 23 char s[N<<1]; 24 void dfs(int x,int p1,int p2){ 25 if(!x)return ; 26 int prej=pre[x][p1][p2].first,prek=pre[x][p1][p2].second; 27 s[x]=(prej==p1)?'Q':'P'; 28 s[len-x+1]=(prek==p2)?'Q':'P'; 29 dfs(x-1,prej,prek); 30 } 31 int main(){ 32 scanf("%d",&n); 33 for(int i=1,y,z;i<=n;i++){ 34 LL x=read();y=z=0; 35 for(int j=0;j<=400&&x-1ll*j*P>=0;j++) 36 if((x-1ll*j*P)%Q==0){y=j;z=(x-1ll*j*P)/Q;break;} 37 if(x>mx)mx=x,nump=y,numq=z; 38 if(y||z)mm[y+z][y]++; 39 } 40 len=nump+numq; 41 memset(f,-0x3f,sizeof f); 42 f[0][0][0]=1; 43 for(int i=1,up,np;i<=(len>>1);i++){ 44 up=min(i,nump); 45 for(int j=0;j<=up;j++){ 46 for(int k=0;k<=up&&j+k<=nump;k++){ 47 np=mm[i][j]+mm[len-i][nump-j]; 48 if(j!=k)np+=mm[i][k]+mm[len-i][nump-k]; 49 f[i][j][k]=f[i-1][j][k];pre[i][j][k]=mk(j,k); 50 if(j&&f[i-1][j-1][k]>f[i][j][k])f[i][j][k]=f[i-1][j-1][k],pre[i][j][k]=mk(j-1,k); 51 if(k&&f[i-1][j][k-1]>f[i][j][k])f[i][j][k]=f[i-1][j][k-1],pre[i][j][k]=mk(j,k-1); 52 if(j&&k&&f[i-1][j-1][k-1]>f[i][j][k])f[i][j][k]=f[i-1][j-1][k-1],pre[i][j][k]=mk(j-1,k-1); 53 f[i][j][k]+=np; 54 } 55 } 56 } 57 if(len&1){ 58 for(int j=0,k,np;j<=nump;j++){ 59 k=nump-j; 60 np=mm[len+1>>1][j];if(j!=k)np+=mm[len+1>>1][k]; 61 if(f[len>>1][j][k]+np>ans){ans=f[len>>1][j][k]+np;ansj=j;ansk=k;s[len+1>>1]='Q';} 62 if(j==nump)break; 63 k=nump-j-1; 64 np=mm[len+1>>1][j+1];if(j!=k)np+=mm[len+1>>1][k+1]; 65 if(f[len>>1][j][k]+np>ans){ans=f[len>>1][j][k]+np;ansj=j;ansk=k;s[len+1>>1]='P';} 66 } 67 } 68 else{ 69 for(int j=0;j<=nump;j++)if(f[len>>1][j][nump-j]>ans) 70 ans=f[len>>1][j][nump-j],ansj=j,ansk=nump-j; 71 } 72 dfs(len>>1,ansj,ansk); 73 printf("%s\n",s+1); 74 return 0; 75 }
晚上回家打了場cf,abc傻逼題,d題打了個貪心,感受很穩,而後c題沒判同一層,d題貪心少跑了一遍,而後就是喜聞樂見的fst了。mdzz。
5.1
勞動節快樂!
先看T1,點分?看數據範圍,暴力70,這麼良心,而後寫了4個那麼namespace,寫了一個多小時,感受點分好像很噁心,就棄了,而後看T2,根本不可作啊,而後看T3,暴力60,而後寫寫寫,寫完想了想,發現這個纔是傻逼點分,直接建出點分樹而後維護個動態開點線段樹就能夠了,而後碼碼碼,編譯過一遍過樣例,而後和暴力拍,發現inf設大了,炸int了,而後改了,以後寫了T2的20分暴力,沒有仔細想。70+25+100=195 rank4。
T1,能夠二分+點分,也能夠點分+超級鋼琴。就tm我bzoj上過不去!!!爲何!!!pbds都過不去,開O3都過不去!!!
1 #pragma GCC optimize ("O3") 2 #include <bits/stdc++.h> 3 #include <ext/pb_ds/priority_queue.hpp> 4 #define N 50505 5 using namespace std; 6 int n,m,size[N],mx[N],allsize,root,tot,vis[N],L,R; 7 int e=1,head[N]; 8 struct edge{ 9 int v,w,next; 10 }ed[N<<1]; 11 void add(int u,int v,int w){ 12 ed[e].v=v;ed[e].w=w; 13 ed[e].next=head[u];head[u]=e++; 14 } 15 void getroot(int x,int fa){ 16 size[x]=1;mx[x]=0; 17 for(int i=head[x];i;i=ed[i].next){ 18 int v=ed[i].v; 19 if(v==fa||vis[v])continue; 20 getroot(v,x); 21 size[x]+=size[v]; 22 mx[x]=max(mx[x],size[v]); 23 } 24 mx[x]=max(mx[x],allsize-size[x]); 25 if(mx[x]<mx[root])root=x; 26 } 27 int a[16*N],l[16*N],r[16*N],maxn[16*N][20],pp[16*N][20],lg[16*N]; 28 void dfs(int x,int fa,int w){ 29 a[++tot]=w; 30 l[tot]=L,r[tot]=R; 31 for(int i=head[x];i;i=ed[i].next){ 32 int v=ed[i].v; 33 if(v==fa||vis[v])continue; 34 dfs(v,x,w+ed[i].w); 35 } 36 } 37 void work(int x){ 38 vis[x]=1; 39 a[++tot]=0; 40 L=tot;R=tot; 41 for(int i=head[x];i;i=ed[i].next){ 42 int v=ed[i].v; 43 if(vis[v])continue; 44 dfs(v,x,ed[i].w); 45 R=tot; 46 } 47 int now=allsize; 48 for(int i=head[x];i;i=ed[i].next){ 49 int v=ed[i].v; 50 if(vis[v])continue; 51 if(size[v]>size[x])allsize=now-size[x]; 52 else allsize=size[v]; 53 root=0;getroot(v,0); 54 work(root); 55 } 56 } 57 void st_init(){ 58 for(int i=1,j=1,cnt=0;i<=tot;i++){ 59 if((j<<1)<i)j<<=1,cnt++; 60 lg[i]=cnt; 61 } 62 for(int i=1;i<=tot;i++)maxn[i][0]=a[i],pp[i][0]=i; 63 for(int i=1;i<=lg[tot];i++){ 64 for(int j=1;j+(1<<i)-1<=tot;j++){ 65 if(maxn[j][i-1]>maxn[j+(1<<i-1)][i-1])maxn[j][i]=maxn[j][i-1],pp[j][i]=pp[j][i-1]; 66 else maxn[j][i]=maxn[j+(1<<i-1)][i-1],pp[j][i]=pp[j+(1<<i-1)][i-1]; 67 } 68 } 69 } 70 struct data{ 71 int l,r,x,pos,val; 72 data(){} 73 data(int a,int b,int c){ 74 l=a;r=b;x=c; 75 int k=lg[b-a+1]; 76 if(maxn[a][k]>maxn[b-(1<<k)+1][k])pos=pp[a][k],val=::a[c]+maxn[a][k]; 77 else pos=pp[b-(1<<k)+1][k],val=::a[c]+maxn[b-(1<<k)+1][k]; 78 } 79 bool operator < (const data &a)const{ 80 return val<a.val; 81 } 82 }; 83 __gnu_pbds::priority_queue<data> q; 84 int main(){ 85 scanf("%d%d",&n,&m); 86 for(int i=1,u,v,w;i<n;i++){ 87 scanf("%d%d%d",&u,&v,&w); 88 add(u,v,w);add(v,u,w); 89 } 90 mx[0]=n+1;root=0;allsize=n; 91 getroot(1,0);work(root); 92 st_init(); 93 for(int i=1;i<=tot;i++)if(l[i]) 94 q.push(data(l[i],r[i],i)); 95 for(int i=1;i<=m;i++){ 96 data now=q.top();q.pop(); 97 printf("%d\n",now.val); 98 if(now.pos>now.l)q.push(data(now.l,now.pos-1,now.x)); 99 if(now.pos<now.r)q.push(data(now.pos+1,now.r,now.x)); 100 } 101 return 0; 102 }
T2,魔法森林增強版,咱們先把點權附到邊上,而後問題轉化成了最小的bs知足將b小於他的邊都加進去有一個>=k的聯通塊,而後咱們至關於要維護一個動態最小生成樹,而後加完一條邊更新答案時,咱們從當前的邊集裏找b最大的,嘗試刪去他,若是刪去他還有大於等於k的聯通塊,咱們就刪去他,不然,他就是這個a對應的最小的b,更新答案便可。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 #define inf 0x7fffffff 8 using namespace std; 9 struct Node{ 10 Node *ch[2],*fa; 11 int size,sm,sxu,maxn,maxid,val,id,rev; 12 Node(); 13 void Rev(); 14 void pushup(); 15 void pushdown(); 16 }*null=new Node(),tree[800500]; 17 Node :: Node(){ 18 ch[0]=ch[1]=fa=null; 19 size=sxu=maxid=id=rev=0; 20 val=maxn=-inf; 21 } 22 void Node :: Rev(){ 23 rev^=1; 24 swap(ch[0],ch[1]); 25 } 26 void Node :: pushup(){ 27 if(ch[0]->maxn>ch[1]->maxn)maxn=ch[0]->maxn,maxid=ch[0]->maxid; 28 else maxn=ch[1]->maxn,maxid=ch[1]->maxid; 29 if(val>maxn)maxn=val,maxid=id; 30 size=ch[0]->size+ch[1]->size+sm+sxu; 31 } 32 void Node :: pushdown(){ 33 if(rev){ 34 ch[0]->Rev(); 35 ch[1]->Rev(); 36 rev=0; 37 } 38 } 39 void rotate(Node *x){ 40 Node *y=x->fa,*z=y->fa; 41 int w=y->ch[1]==x; 42 x->ch[w^1]->fa=y;y->ch[w]=x->ch[w^1]; 43 y->fa=x;x->ch[w^1]=y; 44 if(z->ch[0]==y)z->ch[0]=x; 45 if(z->ch[1]==y)z->ch[1]=x; 46 x->fa=z; 47 y->pushup();x->pushup(); 48 } 49 bool isroot(Node *x){return x->fa->ch[0]!=x&&x->fa->ch[1]!=x;} 50 bool get(Node *x){return x->fa->ch[1]==x;} 51 void pushdown(Node *x){ 52 if(!isroot(x))pushdown(x->fa); 53 x->pushdown(); 54 } 55 void splay(Node *x){ 56 pushdown(x); 57 Node *y; 58 for(;!isroot(x);rotate(x)){ 59 y=x->fa; 60 if(!isroot(y)){ 61 if(get(y)==get(x))rotate(y); 62 else rotate(x); 63 } 64 } 65 } 66 void access(Node *x){ 67 Node *y=null; 68 while(x!=null){ 69 splay(x); 70 x->sxu+=x->ch[1]->size-y->size; 71 x->ch[1]=y; 72 x->pushup(); 73 y=x;x=x->fa; 74 } 75 } 76 void make_root(Node *x){ 77 access(x); 78 splay(x); 79 x->Rev(); 80 } 81 void link(Node *x,Node *y){ 82 make_root(x); 83 make_root(y); 84 x->fa=y; 85 y->sxu+=x->size; 86 y->pushup(); 87 } 88 void cut(Node *x,Node *y){ 89 make_root(x); 90 access(y); 91 splay(y); 92 y->ch[0]=x->fa=null; 93 y->pushup(); 94 } 95 bool check(Node *x,Node *y){ 96 make_root(x); 97 access(y); 98 splay(y); 99 splay(x); 100 return (y->fa!=null); 101 } 102 struct data{ 103 int u,v,id,a,b; 104 bool operator < (const data & x)const{ 105 if(b==x.b)return id<x.id; 106 return b<x.b; 107 } 108 bool operator == (const data & x)const{ 109 return id==x.id; 110 } 111 }d[500500]; 112 bool cmpa(data x,data y){return x.a<y.a;} 113 struct que{ 114 priority_queue<data> a,b; 115 void ins(data x){a.push(x);} 116 void del(data x){b.push(x);} 117 void mt(){while(!b.empty()&&a.top()==b.top())a.pop(),b.pop();} 118 data top(){mt();return a.top();} 119 int size(){mt();return a.size();} 120 void pop(){mt();a.pop();} 121 }q; 122 int a[300500],b[300500],n,m,K,ans,cnt; 123 int main(){ 124 scanf("%d%d%d",&n,&m,&K); 125 for(int i=1;i<=n;i++) 126 scanf("%d%d",&a[i],&b[i]); 127 if(K==1){ 128 ans=inf; 129 for(int i=1;i<=n;i++)ans=min(ans,a[i]+b[i]); 130 printf("%d\n",ans); 131 return 0; 132 } 133 for(int i=1;i<=m;i++){ 134 scanf("%d%d",&d[i].u,&d[i].v); 135 d[i].a=max(a[d[i].u],a[d[i].v]); 136 d[i].b=max(b[d[i].u],b[d[i].v]); 137 } 138 sort(d+1,d+m+1,cmpa); 139 for(int i=1;i<=m;i++)d[i].id=i; 140 for(int i=1;i<=n;i++){ 141 tree[i].ch[0]=tree[i].ch[1]=tree[i].fa=null; 142 tree[i].id=tree[i].maxid=i; 143 tree[i].size=tree[i].sm=1; 144 tree[i].rev=tree[i].sxu=0; 145 tree[i].val=tree[i].maxn=-inf; 146 } 147 for(int i=n+1;i<=n+m;i++){ 148 tree[i].ch[0]=tree[i].ch[1]=tree[i].fa=null; 149 tree[i].id=tree[i].maxid=i; 150 tree[i].size=tree[i].sm=0; 151 tree[i].rev=tree[i].sxu=0; 152 tree[i].val=tree[i].maxn=d[i-n].b; 153 } 154 cnt=0; 155 ans=inf; 156 for(int i=1;i<=m;i++){ 157 int u=d[i].u,v=d[i].v; 158 if(!check(&tree[u],&tree[v])){ 159 make_root(&tree[u]);if(tree[u].size>=K)cnt--; 160 make_root(&tree[v]);if(tree[v].size>=K)cnt--; 161 link(&tree[u],&tree[n+i]); 162 link(&tree[v],&tree[n+i]); 163 make_root(&tree[n+i]);if(tree[n+i].size>=K)cnt++; 164 q.ins(d[i]); 165 } 166 else{ 167 make_root(&tree[u]);access(&tree[v]);splay(&tree[v]); 168 if(tree[v].maxn>d[i].b){ 169 int y=tree[v].maxid; 170 cut(&tree[y],&tree[d[y-n].u]); 171 cut(&tree[y],&tree[d[y-n].v]); 172 link(&tree[u],&tree[n+i]); 173 link(&tree[v],&tree[n+i]); 174 q.ins(d[i]); 175 q.del(d[y-n]); 176 } 177 } 178 if(!cnt)continue; 179 while(q.size()){ 180 data now=q.top(); 181 make_root(&tree[n+now.id]);if(tree[n+now.id].size>=K)cnt--; 182 cut(&tree[n+now.id],&tree[now.u]); 183 cut(&tree[n+now.id],&tree[now.v]); 184 make_root(&tree[now.u]);if(tree[now.u].size>=K)cnt++; 185 make_root(&tree[now.v]);if(tree[now.v].size>=K)cnt++; 186 if(!cnt){ 187 cnt++; 188 link(&tree[n+now.id],&tree[now.u]); 189 link(&tree[n+now.id],&tree[now.v]); 190 ans=min(ans,d[i].a+now.b); 191 break; 192 } 193 q.pop(); 194 } 195 } 196 if(ans<inf)printf("%d\n",ans); 197 else puts("no solution"); 198 return 0; 199 }
T3,裸點分,貌似還有一系列根號作法。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 100500 7 #define inf 0x3fffffff 8 using namespace std; 9 int root,size[N],mx[N],allsize,n,m; 10 int e=1,head[N]; 11 struct edge{ 12 int v,w,next; 13 }ed[N<<1]; 14 void add(int u,int v,int w){ 15 ed[e].v=v;ed[e].w=w; 16 ed[e].next=head[u];head[u]=e++; 17 } 18 int dep[N],val[N],fa[N][18]; 19 void dfs(int x,int d,int vv){ 20 dep[x]=d; 21 val[x]=vv; 22 for(int i=1;(1<<i)<=d;i++) 23 fa[x][i]=fa[fa[x][i-1]][i-1]; 24 for(int i=head[x];i;i=ed[i].next){ 25 int v=ed[i].v; 26 if(v==fa[x][0])continue; 27 fa[v][0]=x; 28 dfs(v,d+1,vv+ed[i].w); 29 } 30 } 31 int getlca(int x,int y){ 32 if(dep[x]<dep[y])swap(x,y); 33 for(int i=16;~i;i--) 34 if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; 35 if(x==y)return x; 36 for(int i=16;~i;i--) 37 if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; 38 return fa[x][0]; 39 } 40 int getdis(int x,int y){ 41 return val[x]+val[y]-2*val[getlca(x,y)]; 42 } 43 int par[N],vis[N]; 44 void getroot(int x,int fa){ 45 size[x]=1;mx[x]=0; 46 for(int i=head[x];i;i=ed[i].next){ 47 int v=ed[i].v; 48 if(v==fa||vis[v])continue; 49 getroot(v,x); 50 size[x]+=size[v]; 51 mx[x]=max(mx[x],size[v]); 52 } 53 mx[x]=max(mx[x],allsize-size[x]); 54 if(mx[x]<mx[root])root=x; 55 } 56 void work(int x){ 57 vis[x]=1; 58 int now=allsize; 59 for(int i=head[x];i;i=ed[i].next){ 60 int v=ed[i].v; 61 if(vis[v])continue; 62 if(size[v]>size[x])allsize=now-size[x]; 63 else allsize=size[v]; 64 root=0;getroot(v,0); 65 par[root]=x; 66 work(root); 67 } 68 } 69 int sz,rot[N],lon[N<<8],ron[N<<8],mn[N<<8]; 70 void update(int &rt,int l,int r,int x,int y){ 71 if(!rt)rt=++sz,mn[rt]=inf; 72 mn[rt]=min(mn[rt],y); 73 if(l==r)return ; 74 int mid=(l+r)>>1; 75 if(x<=mid)update(lon[rt],l,mid,x,y); 76 else update(ron[rt],mid+1,r,x,y); 77 } 78 int query(int rt,int l,int r,int x,int y){ 79 if(!rt)return inf; 80 if(x<=l&&r<=y)return mn[rt]; 81 int mid=(l+r)>>1; 82 if(y<=mid)return query(lon[rt],l,mid,x,y); 83 if(x>mid)return query(ron[rt],mid+1,r,x,y); 84 return min(query(lon[rt],l,mid,x,y),query(ron[rt],mid+1,r,x,y)); 85 } 86 void build(){ 87 dfs(1,1,0); 88 allsize=n;root=0;mx[0]=n+1; 89 getroot(1,0);work(root); 90 for(int i=1;i<=n;i++) 91 for(int j=i;j;j=par[j]) 92 update(rot[j],1,n,i,getdis(i,j)); 93 } 94 int query(int l,int r,int x){ 95 int ans=query(rot[x],1,n,l,r); 96 for(int i=par[x];i;i=par[i]) 97 ans=min(ans,getdis(x,i)+query(rot[i],1,n,l,r)); 98 return ans; 99 } 100 int main(){ 101 scanf("%d",&n); 102 for(int i=1,u,v,w;i<n;i++){ 103 scanf("%d%d%d",&u,&v,&w); 104 add(u,v,w);add(v,u,w); 105 } 106 build(); 107 scanf("%d",&m); 108 int l,r,x; 109 while(m--){ 110 scanf("%d%d%d",&l,&r,&x); 111 printf("%d\n",query(l,r,x)); 112 } 113 return 0; 114 }
我愛拜仁。
5.3
今天三道水題,T1double炸精我又輸出的lf而後就爆零了,之後要特別注意這一點。
考試看完題,發現都是原題,先寫T1,而後T3,最後T2,都拍了拍,以爲挺穩的,而後T1就掛了。最後還寫了一個多小時的果凍運輸的暴搜,下午試了試效率極低。
T1,裸的旋轉卡殼。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 100500 7 #define LL long long 8 using namespace std; 9 int n,top,tim; 10 LL ans; 11 struct point{ 12 LL x,y; 13 point(){x=y=0;} 14 point(LL a,LL b){x=a;y=b;} 15 point operator - (point a){return point(x-a.x,y-a.y);} 16 LL operator * (point a){return x*a.y-y*a.x;} 17 }p[N],q[N]; 18 LL dis(point a){ 19 return a.x*a.x+a.y*a.y; 20 } 21 bool cmp(point a,point b){ 22 if((a-p[1])*(b-p[1])==0)return dis(a-p[1])<dis(b-p[1]); 23 return (a-p[1])*(b-p[1])>0; 24 } 25 void graham(){ 26 for(int i=2;i<=n;i++) 27 if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[i].y)) 28 swap(p[1],p[i]); 29 sort(p+2,p+n+1,cmp); 30 top=1;q[top]=p[1]; 31 for(int i=2;i<=n;i++){ 32 while(top>1&&(p[i]-q[top])*(q[top]-q[top-1])>=0)top--; 33 q[++top]=p[i]; 34 } 35 } 36 int main(){ 37 scanf("%d",&n); 38 for(int i=1;i<=n;i++) 39 scanf("%lld%lld",&p[i].x,&p[i].y); 40 graham(); 41 q[top+1]=q[1]; 42 for(int i=1,j=2,k=1,l=2;i<=top;i++){ 43 while((q[i+1]-q[i])*(q[j+1]-q[i])>(q[i+1]-q[i])*(q[j]-q[i])){ 44 if(j==l){l++;if(l==top+1)l=1;} 45 j++;if(j==top+1)j=1; 46 } 47 while((q[i]-q[j])*(q[k+1]-q[j])>(q[i]-q[j])*(q[k]-q[j])){k++;if(k==top+1)k=1;} 48 while((q[j]-q[i])*(q[l+1]-q[i])>(q[j]-q[i])*(q[l]-q[i])){l++;if(l==top+1)l=1;} 49 ans=max(ans,(q[i]-q[j])*(q[k]-q[j])+(q[j]-q[i])*(q[l]-q[i])); 50 } 51 if(ans&1)printf("%lld.5\n",ans>>1); 52 else printf("%lld.0\n",ans>>1); 53 return 0; 54 }
T2,航海艦隊弱化版,能夠直接兩種東西分開卷,也能夠像我同樣傻逼的按照bzoj4503同樣搞一下。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define mod 998244353 8 #define N 526666 9 using namespace std; 10 int n,m,q,l1,l2,tot,num,len,rev[N],ans[N]; 11 int a[N],a2[N],one[N],b[N],c[N],bc[N],b2c[N],fin,fi,fj; 12 char s[505]; 13 int qp(int a,int b){ 14 int c=1; 15 for(;b;b>>=1,a=1ll*a*a%mod) 16 if(b&1)c=1ll*c*a%mod; 17 return c; 18 } 19 void ntt(int *a,int o){ 20 register int i,j,k,dan,now,t; 21 for(i=0;i<len;++i)if(i<rev[i])swap(a[i],a[rev[i]]); 22 for(k=2;k<=len;k<<=1){ 23 dan=qp(3,(o==1)?((mod-1)/k):(mod-1-(mod-1)/k)); 24 for(i=0;i<len;i+=k){ 25 now=1; 26 for(j=0;j<(k>>1);++j,now=1ll*now*dan%mod){ 27 t=1ll*a[i+j+(k>>1)]*now%mod; 28 a[i+j+(k>>1)]=(a[i+j]-t+mod)%mod; 29 a[i+j]=(a[i+j]+t)%mod; 30 } 31 } 32 } 33 if(o==-1){ 34 int inv=qp(len,mod-2); 35 for(i=0;i<len;++i)a[i]=1ll*a[i]*inv%mod; 36 } 37 } 38 int main(){ 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=n;i++){ 41 scanf("%s",s+1); 42 for(int j=1;j<=m;j++){ 43 if(s[j]=='G')a[tot++]=1; 44 else a[tot++]=2; 45 } 46 } 47 for(int i=0;i<tot;i++)a2[i]=a[i]*a[i]; 48 for(int i=0;i<tot;i++)one[i]=1; 49 for(len=1;len<=(2*tot);len<<=1); 50 for(int i=0;i<len;i++){ 51 if(i&1)rev[i]=(rev[i>>1]>>1)|(len>>1); 52 else rev[i]=rev[i>>1]>>1; 53 } 54 ntt(a2,1); 55 ntt(a,1); 56 ntt(one,1); 57 scanf("%d",&q); 58 while(q--){ 59 scanf("%d%d",&l1,&l2); 60 num=0; 61 for(int i=1;i<=l1;i++){ 62 scanf("%s",s+1); 63 for(int j=1;j<=l2;j++){ 64 if(s[j]=='G')b[num++]=1; 65 else b[num++]=2; 66 c[num-1]=1; 67 } 68 if(i==l1)break; 69 for(int j=l2+1;j<=m;j++){ 70 b[num++]=0; 71 c[num-1]=0; 72 } 73 } 74 reverse(b,b+num); 75 reverse(c,c+num); 76 for(int i=0;i<num;i++){ 77 b2c[i]=b[i]*b[i]*c[i]; 78 bc[i]=mod-2*b[i]*c[i]; 79 } 80 for(int i=num;i<len;i++)bc[i]=b2c[i]=c[i]=0; 81 ntt(c,1);ntt(bc,1);ntt(b2c,1); 82 for(int i=0;i<len;i++) 83 ans[i]=((1ll*a2[i]*c[i]%mod+1ll*a[i]*bc[i]%mod)%mod+1ll*one[i]*b2c[i]%mod)%mod; 84 ntt(ans,-1); 85 fin=l1*l2+1; 86 for(int i=1;i<=n-l1+1;i++) 87 for(int j=1;j<=m-l2+1;j++) 88 if(ans[(i-1)*m+j+num-2]<fin){ 89 fin=ans[(i-1)*m+j+num-2]; 90 fi=i;fj=j; 91 } 92 printf("%d %d\n",fi,fj); 93 } 94 return 0; 95 }
T3,弗洛伊德矩陣快速冪
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 void getmin(int &a,int b){a>b?a=b:0;} 9 int n,m,ans,up; 10 struct mart{ 11 int a[303][303]; 12 mart(){memset(a,0x3f,sizeof a);} 13 }A[11]; 14 bool check(mart a){ 15 for(int i=1;i<=n;i++) 16 if(a.a[i][i]<0)return 1; 17 return 0; 18 } 19 mart mul(mart a,mart b){ 20 mart c; 21 for(int i=1;i<=n;i++) 22 for(int j=1;j<=n;j++)if(a.a[i][j]<inf) 23 for(int k=1;k<=n;k++)if(b.a[j][k]<inf) 24 getmin(c.a[i][k],a.a[i][j]+b.a[j][k]); 25 return c; 26 } 27 int main(){ 28 scanf("%d%d",&n,&m); 29 for(int i=1,u,v,w;i<=m;i++){ 30 scanf("%d%d%d",&u,&v,&w); 31 A[0].a[u][v]=w; 32 } 33 for(int i=1;i<=n;i++)A[0].a[i][i]=0; 34 for(up=1;(1<<up)<=n;up++) 35 A[up]=mul(A[up-1],A[up-1]);up--; 36 for(int i=1;i<=n;i++)A[up+1].a[i][i]=0; 37 for(int i=up;~i;i--){ 38 A[up+2]=mul(A[up+1],A[i]); 39 if(!check(A[up+2]))ans+=(1<<i),A[up+1]=A[up+2]; 40 if(ans>n){puts("0");return 0;} 41 } 42 ans++; 43 if(ans>n)puts("0"); 44 else printf("%d\n",ans); 45 return 0; 46 }
虛...
5.4
又tm炸了。考試先看T1,感受十分不可作,寫了30分暴力就棄療了,看T2,更不可作,先寫了60,而後找不着規律,推不出式子。而後看T3,辛辛苦苦打了很久,原本感受40穩,沒準還能多騙點分,而後由於評測機的種種傻逼,mle成15。沒有而後了30+60+15=105 rank8
T1,kosaraju+bitset+分塊+st表,kosalaju好簡單啊!
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #include <cassert> 8 #define N 155 9 #define ull unsigned long long 10 #define oo 0x7fffffffffffffff 11 using namespace std; 12 struct Bit{ 13 ull a[3]; 14 void clear(){a[0]=a[1]=a[2]=0;} 15 int get(int x){return (a[x>>6]>>(x&63))&1;} 16 void Or(int x){a[x>>6]|=1ll<<(x&63);} 17 void Xor(int x){a[x>>6]^=1ll<<(x&63);} 18 int Lowbit(){ 19 if(a[0])return __builtin_ctzll(a[0]); 20 if(a[1])return __builtin_ctzll(a[1])+64; 21 if(a[2])return __builtin_ctzll(a[2])+128; 22 return -1; 23 } 24 Bit operator & (Bit B){ 25 Bit ans; 26 ans.a[0]=a[0]&B.a[0]; 27 ans.a[1]=a[1]&B.a[1]; 28 ans.a[2]=a[2]&B.a[2]; 29 return ans; 30 } 31 bool operator ! (){return !a[0]&&!a[1]&&!a[2];} 32 }vis,g1[N],g2[N],st1[600][10][N],st2[600][10][N]; 33 int n,m,mm,tot,qr,q[N],top,be[300500],en[600],lg[600],num,ans; 34 struct data{int u,v;}d[300500]; 35 void dfs1(int x){ 36 vis.Xor(x); 37 Bit now; 38 while(1){ 39 now=vis&g1[x]; 40 if(!now)break; 41 int v=now.Lowbit(); 42 dfs1(v); 43 } 44 q[++top]=x; 45 } 46 void dfs2(int x){ 47 vis.Xor(x);num++; 48 Bit now; 49 while(1){ 50 now=vis&g2[x]; 51 if(!now)break; 52 int v=now.Lowbit(); 53 dfs2(v); 54 } 55 } 56 int main(){ 57 scanf("%d%d%d",&n,&m,&qr); 58 for(int i=1;i<=m;i++)scanf("%d%d",&d[i].u,&d[i].v); 59 mm=sqrt(m); 60 for(int i=1;i<=m;i++){ 61 be[i]=(i-1)/mm+1; 62 en[be[i]]=i; 63 st1[be[i]][0][d[i].u].Or(d[i].v); 64 st2[be[i]][0][d[i].v].Or(d[i].u); 65 } 66 tot=be[m]; 67 for(int i=1,j=1,cnt=0;i<=tot;i++){ 68 if((j<<1)<i)j<<=1,cnt++; 69 lg[i]=cnt; 70 } 71 for(int i=1;i<=lg[tot];i++){ 72 for(int j=1;j+(1<<i)-1<=tot;j++){ 73 for(int k=1;k<=n;k++){ 74 st1[j][i][k].a[0]=st1[j][i-1][k].a[0]|st1[j+(1<<i-1)][i-1][k].a[0]; 75 st1[j][i][k].a[1]=st1[j][i-1][k].a[1]|st1[j+(1<<i-1)][i-1][k].a[1]; 76 st1[j][i][k].a[2]=st1[j][i-1][k].a[2]|st1[j+(1<<i-1)][i-1][k].a[2]; 77 st2[j][i][k].a[0]=st2[j][i-1][k].a[0]|st2[j+(1<<i-1)][i-1][k].a[0]; 78 st2[j][i][k].a[1]=st2[j][i-1][k].a[1]|st2[j+(1<<i-1)][i-1][k].a[1]; 79 st2[j][i][k].a[2]=st2[j][i-1][k].a[2]|st2[j+(1<<i-1)][i-1][k].a[2]; 80 } 81 } 82 } 83 int l,r; 84 while(qr--){ 85 scanf("%d%d",&l,&r); 86 for(int i=1;i<=n;i++)g1[i].clear(),g2[i].clear(); 87 if(be[l]==be[r]){ 88 for(int i=l;i<=r;i++){ 89 g1[d[i].u].Or(d[i].v); 90 g2[d[i].v].Or(d[i].u); 91 } 92 } 93 else{ 94 for(int i=l;i<=en[be[l]];i++){ 95 g1[d[i].u].Or(d[i].v); 96 g2[d[i].v].Or(d[i].u); 97 } 98 for(int i=en[be[r]-1]+1;i<=r;i++){ 99 g1[d[i].u].Or(d[i].v); 100 g2[d[i].v].Or(d[i].u); 101 } 102 if(be[l]+1<be[r]){ 103 int k=lg[be[r]-be[l]-1]; 104 for(int i=1;i<=n;i++){ 105 g1[i].a[0]|=st1[be[l]+1][k][i].a[0]|st1[be[r]-(1<<k)][k][i].a[0]; 106 g1[i].a[1]|=st1[be[l]+1][k][i].a[1]|st1[be[r]-(1<<k)][k][i].a[1]; 107 g1[i].a[2]|=st1[be[l]+1][k][i].a[2]|st1[be[r]-(1<<k)][k][i].a[2]; 108 g2[i].a[0]|=st2[be[l]+1][k][i].a[0]|st2[be[r]-(1<<k)][k][i].a[0]; 109 g2[i].a[1]|=st2[be[l]+1][k][i].a[1]|st2[be[r]-(1<<k)][k][i].a[1]; 110 g2[i].a[2]|=st2[be[l]+1][k][i].a[2]|st2[be[r]-(1<<k)][k][i].a[2]; 111 } 112 } 113 } 114 vis.clear(); 115 for(int i=1;i<=n;i++)vis.Or(i); 116 top=0; 117 for(int i=1;i<=n;i++) 118 if(vis.get(i))dfs1(i); 119 vis.clear(); 120 for(int i=1;i<=n;i++)vis.Or(i); 121 ans=0; 122 for(int i=n;i;i--){ 123 if(vis.get(q[i])){ 124 num=0; 125 dfs2(q[i]); 126 ans+=num*(num-1)/2; 127 } 128 } 129 printf("%d\n",ans); 130 } 131 }
T2,優秀的dp,f[i]表示i個點組成的有向徹底強聯通圖的方案數。每個有向徹底圖縮點後必定是一堆強聯通塊組成的一條鏈,而後1號點能走的就是他的強聯通塊大小以及後面的全部強聯通塊大小之和。
1 #pragma GCC optimize ("O3") 2 #include <bits/stdc++.h> 3 #define N 2005 4 using namespace std; 5 int n,P,C[N][N],f[N],g[N],ans[N]; 6 int qp(int a,int b){ 7 int c=1; 8 for(;b;b>>=1,a=1ll*a*a%P) 9 if(b&1)c=1ll*c*a%P; 10 return c; 11 } 12 void UPD(int &a,int b){a=(a+b>=P)?(a+b-P):(a+b);} 13 int main(){ 14 scanf("%d%d",&n,&P); 15 for(int i=0;i<=n;i++){ 16 C[i][0]=1; 17 for(int j=1;j<=i;j++) 18 C[i][j]=(C[i-1][j-1]+C[i-1][j])%P; 19 } 20 g[0]=1; 21 for(int i=1;i<=n;i++)f[i]=g[i]=qp(2,i*(i-1)/2); 22 for(int i=1;i<=n;i++) 23 for(int j=1;j<i;j++) 24 UPD(f[i],P-1ll*C[i][j]*f[j]%P*g[i-j]%P); 25 for(int i=1;i<=n;i++) 26 for(int j=0;j<=n-i;j++) 27 UPD(ans[i+j],1ll*f[i]*C[n-1][i-1]%P*g[j]%P*C[n-i][j]%P*g[n-i-j]%P); 28 for(int i=1;i<=n;i++)printf("%d\n",ans[i]); 29 }
T3,對於出現次數大於$\sqrt{n}$的左端點,咱們O(n)掃來統計答案,其餘的暴力分塊查詢。v.size()賊慢。
1 #pragma GCC optimize ("O3") 2 #include <bits/stdc++.h> 3 #include <unordered_map> 4 #define N 150005 5 #define MP unordered_map<int,int> 6 #define pb push_back 7 #define min(a,b) ((a)<(b)?(a):(b)) 8 using namespace std; 9 char B[1<<15],*S=B,*T=B; 10 #define getc (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++) 11 inline int read() 12 { 13 register int x=0;register char c=getc; 14 while(c<'0'|c>'9')c=getc; 15 while(c>='0'&c<='9')x=10*x+(c^48),c=getc; 16 return x; 17 } 18 MP pp; 19 vector <int> vv[N],v1[N],v2[N]; 20 int n,m,nn,K,a[N],s[N],cnt[N],de1[N],de2[N],sum[N],vvv[N]; 21 int tot,be[N],en[1050],val[N],tag[1050]; 22 struct data{int l,r,w;}d[N]; 23 inline void calc(int val){ 24 register int i,j,u,v; 25 for(i=n,u=0,v=0;i;--i){ 26 u+=de1[i]; 27 cnt[i]=cnt[i+1]; 28 if(s[i]==(val^K))cnt[i]++,v+=u; 29 for(j=0;j<v1[i+1].size();++j) 30 v-=(cnt[i+1]-cnt[d[v1[i+1][j]].r+1])*d[v1[i+1][j]].w; 31 if(s[i-1]==val)sum[i]+=v; 32 } 33 for(i=1,u=0,v=0;i<=n;++i){ 34 u+=de2[i]; 35 cnt[i]=cnt[i-1]; 36 if(s[i-1]==val)cnt[i]++,v+=u; 37 for(j=0;j<v2[i-1].size();++j) 38 v-=(cnt[i-1]-cnt[d[v2[i-1][j]].l-1])*d[v2[i-1][j]].w; 39 if(s[i]==(val^K))sum[i+1]-=v; 40 } 41 } 42 int main(){ 43 //freopen("test.in","r",stdin); 44 //freopen("3.out","w",stdout); 45 register int i,j,k,l,now,pos,sz; 46 n=read();m=read();K=read(); 47 nn=555; 48 for(i=1;i<=n;++i){ 49 a[i]=read(); 50 s[i]=s[i-1]^a[i]; 51 if(!pp[s[i-1]])pp[s[i-1]]=++tot,vvv[tot]=s[i-1]; 52 vv[pp[s[i-1]]].pb(i); 53 be[i]=(i-1)/nn+1; 54 en[be[i]]=i; 55 } 56 for(i=1;i<=m;++i){ 57 d[i].l=read();d[i].r=read();d[i].w=read(); 58 de1[d[i].r]+=d[i].w;de1[d[i].l-1]-=d[i].w; 59 de2[d[i].l]+=d[i].w;de2[d[i].r+1]-=d[i].w; 60 v1[d[i].l].pb(i);v2[d[i].r].pb(i); 61 } 62 for(i=1;i<=tot;++i) 63 if(vv[i].size()>=nn)calc(vvv[i]); 64 for(i=n;i;--i){ 65 sz=v2[i].size(); 66 for(j=0;j<sz;++j){ 67 l=d[v2[i][j]].l; 68 pos=min(en[be[l]],i); 69 if(pos-l+1>l-en[be[l]-1]){ 70 for(k=en[be[l]-1]+1;k<l;++k)val[k]-=d[v2[i][j]].w; 71 tag[be[l]]+=d[v2[i][j]].w; 72 } 73 else{ 74 for(k=l;k<=pos;++k)val[k]+=d[v2[i][j]].w; 75 } 76 for(k=be[l]+1;k<=be[i];++k)tag[k]+=d[v2[i][j]].w; 77 } 78 sz=vv[pp[s[i]^K]].size(); 79 if(sz<nn){ 80 now=0; 81 for(j=0;j<sz;++j){ 82 pos=vv[pp[s[i]^K]][j]; 83 if(pos>i)break; 84 sum[pos]+=val[pos]+tag[be[pos]]; 85 now+=val[pos]+tag[be[pos]]; 86 } 87 sum[i+1]-=now; 88 } 89 } 90 for(i=1,now=0;i<=n;++i){ 91 now=now+sum[i]; 92 printf("%d ",now&(1073741823)); 93 }puts(""); 94 return 0; 95 }
5.5
考的是jsoi round2 day2 被暴虐。
先看T1,計算幾何,凸包求交,半平面交有70?而後看T2,50送的?T3,主席樹裸題?而後先去寫T2,寫了20暴力,發現方案數不是很好搞,而後找了找規律,發現能夠暴力枚舉第一個塊的長寬,而後組合數什麼的亂搞一下,推完打完快2h了,而後趕忙去看T3,只會log2?無論了,先寫吧,寫完發現二分的log能夠直接在線段樹上跑,而後就去掉了,改了改拍上了,極限數據大概要跑3s左右,虛。又卡了卡常,沒啥用,而後就剩30min左右了,趕忙去看T1,寫了一半感受本身寫不出來半平面交了,剛打算棄遼,而後教練說延長15min,瞬間不虛,推了推式子,卻是一遍過樣例了,以後也沒啥時間了,就沒測大點。40+50+100=190 rank1,T1被卡log了。貌似在js剛進前十?菜。
T1,閔科夫斯基和,沒據說過。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define N 100050 8 #define LL long long 9 using namespace std; 10 int n,m,qr,top,tot; 11 struct point{ 12 int x,y; 13 point(){x=y=0;} 14 point(int a,int b){x=a;y=b;} 15 point operator + (point a){return point(x+a.x,y+a.y);} 16 point operator - (point a){return point(x-a.x,y-a.y);} 17 LL operator * (point a){return 1ll*x*a.y-1ll*y*a.x;} 18 }p1[N],p2[N],p[N],q[N],B; 19 LL getdis(point a){ 20 return sqrt(1ll*a.x*a.x+1ll*a.y*a.y); 21 } 22 bool cmpp(point a,point b){ 23 LL now=(a-B)*(b-B); 24 if(now==0)return getdis(a-B)<getdis(b-B); 25 return now>0; 26 } 27 void graham(point *a,int &n){ 28 for(int i=2;i<=n;i++) 29 if(a[i].x<a[1].x||(a[i].x==a[1].x&&a[i].y<a[1].y)) 30 swap(a[1],a[i]); 31 B=a[1]; 32 sort(a+2,a+n+1,cmpp); 33 top=1;q[1]=a[1]; 34 for(int i=2;i<=n;i++){ 35 while(top>1&&(a[i]-q[top])*(q[top]-q[top-1])>=0)top--; 36 q[++top]=a[i]; 37 } 38 for(int i=1;i<=top;i++)a[i]=q[i]; 39 n=top; 40 } 41 42 struct line{ 43 point v; 44 double k; 45 line(){} 46 line(point a,point b){ 47 v=b-a; 48 k=atan2(v.y,v.x); 49 } 50 }l[N]; 51 #define _P -(acos(-1.0)/2.0) 52 bool cmpl(line a,line b){ 53 if(a.k==_P)return 0; 54 if(b.k==_P)return 1; 55 if(a.k>_P&&b.k>_P)return a.k<b.k; 56 if(a.k<_P&&b.k<_P)return a.k<b.k; 57 return a.k>_P; 58 } 59 60 int main(){ 61 scanf("%d%d%d",&n,&m,&qr); 62 for(int i=1;i<=n;i++)scanf("%d%d",&p1[i].x,&p1[i].y); 63 for(int i=1;i<=m;i++){ 64 scanf("%d%d",&p2[i].x,&p2[i].y); 65 p2[i].x*=-1;p2[i].y*=-1; 66 } 67 graham(p1,n); 68 graham(p2,m); 69 for(int i=1;i<n;i++)l[i]=line(p1[i],p1[i+1]); 70 l[n]=line(p1[n],p1[1]); 71 for(int i=1;i<m;i++)l[n+i]=line(p2[i],p2[i+1]); 72 l[n+m]=line(p2[m],p2[1]); 73 sort(l+1,l+n+m+1,cmpl); 74 p[1]=p1[1]+p2[1]; 75 for(int i=1;i<n+m;i++)p[i+1]=p[i]+l[i].v; 76 tot=n+m; 77 graham(p,tot); 78 point now; 79 while(qr--){ 80 int l=2,r=tot,mid,fin=1; 81 scanf("%d%d",&now.x,&now.y); 82 while(l<=r){ 83 mid=(l+r)>>1; 84 if((p[mid]-p[1])*(now-p[1])>=0)fin=mid,l=mid+1; 85 else r=mid-1; 86 } 87 if(fin==tot||fin==1){puts("0");continue;} 88 if((now-p[fin])*(p[fin+1]-p[fin])>0)puts("0"); 89 else puts("1"); 90 } 91 }
T2卻是一道不錯的題目,咱們發現每走一步,至關於限制了lcm(n,m)步,由於若是(1,1)走到了(1,2),那麼(n,2)就只能走到(n,3)。而後咱們如今就只需走gcd步就能獲得對應的遍歷全圖的方案,因而咱們設第一個塊豎着走了x步,橫着走了y步,咱們發現一個方案是合法的,當且僅當gcd(x,n)=1&&gcd(y,m)=1,這個是由於要遍歷n和m的所有剩餘系。而後咱們就能夠枚舉x,而後對於每一個塊dp在這個塊裏撞到障礙的方案數,由於每一個塊走的是同樣的,因此還要保證在以前的全部塊中這種走法是合理的。時間複雜度$O(nm\frac{gcd(n,m)}{4})$,常數極小。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define mod 998244353 7 #define N 55 8 using namespace std; 9 int T,n,m,l,g,ans,C[N<<1][N<<1],blo[N][N],f1[N][N],f2[N][N],vis[N][N]; 10 int gcd(int a,int b){return !b?a:gcd(b,a%b);} 11 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 12 char s[N]; 13 int main(){ 14 scanf("%d",&T); 15 for(int i=0;i<=100;i++){ 16 C[i][0]=1; 17 for(int j=1;j<=i;j++) 18 C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; 19 } 20 while(T--){ 21 scanf("%d%d",&n,&m); 22 for(int i=0;i<n;i++){ 23 scanf("%s",s); 24 for(int j=0;j<m;j++) 25 blo[i][j]=s[j]-'0'; 26 } 27 g=gcd(n,m); 28 l=n*m/g; 29 ans=0; 30 for(int x=1,y,nx,ny,rest;x<=g;x++){ 31 if(gcd(x,n)!=1||gcd(g-x,m)!=1)continue; 32 y=g-x; 33 nx=ny=0; 34 memset(vis,0,sizeof vis); 35 memset(f1,0,sizeof f1); 36 memset(f2,0,sizeof f2); 37 for(int i=0;i<=x;i++){ 38 f1[i][0]=1; 39 for(int j=1;j<=y;j++)f1[i][j]=(f1[i][j-1]+f1[i-1][j])%mod; 40 } 41 for(int i=x;~i;i--){ 42 f2[i][y]=1; 43 for(int j=y-1;~j;j--)f2[i][j]=(f2[i][j+1]+f2[i+1][j])%mod; 44 } 45 rest=C[x+y][x]; 46 for(int t=1;t<=l;t++){ 47 for(int i=0;i<=x;i++){ 48 for(int j=0;j<=y;j++){ 49 if(j==0){ 50 if(i==0)f1[i][j]=1; 51 else f1[i][j]=f1[i-1][j]; 52 } 53 else{ 54 if(i==0)f1[i][j]=f1[i][j-1]; 55 else f1[i][j]=(f1[i-1][j]+f1[i][j-1])%mod; 56 } 57 if(vis[i][j])f1[i][j]=0; 58 if(blo[(nx+i)%n][(ny+j)%m]){ 59 UPD(ans,1ll*f1[i][j]*f2[i][j]%mod*((t-1)*g+i+j)%mod); 60 UPD(rest,mod-1ll*f1[i][j]*f2[i][j]%mod); 61 vis[i][j]=1;f1[i][j]=0; 62 } 63 } 64 } 65 if(!rest)break; 66 for(int i=x;~i;i--){ 67 for(int j=y;~j;j--){ 68 if(j==y){ 69 if(i==x)f2[i][j]=1; 70 else f2[i][j]=f2[i+1][j]; 71 } 72 else{ 73 if(i==x)f2[i][j]=f2[i][j+1]; 74 else f2[i][j]=(f2[i+1][j]+f2[i][j+1])%mod; 75 } 76 if(vis[i][j])f2[i][j]=0; 77 } 78 } 79 nx=(nx+x)%n; 80 ny=(ny+y)%m; 81 } 82 } 83 printf("%d\n",ans); 84 } 85 return 0; 86 }
T3,傻逼主席樹。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define N 500500 8 #define maxn 2000000 9 #define LL long long 10 using namespace std; 11 char B[1<<15],*S=B,*T=B; 12 #define getc (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++) 13 inline int read() 14 { 15 register int x=0;register char c=getc; 16 while(c<'0'|c>'9')c=getc; 17 while(c>='0'&c<='9')x=10*x+(c^48),c=getc; 18 return x; 19 } 20 int n,m; 21 int sz,root[N],lon[N<<5],ron[N<<5],s1[N<<5]; 22 LL s2[N<<5]; 23 void insert(int &rt,int o,int l,int r,int x){ 24 rt=++sz; 25 lon[rt]=lon[o],ron[rt]=ron[o]; 26 s1[rt]=s1[o]+1;s2[rt]=s2[o]+x; 27 if(l==r)return ; 28 int mid=(l+r)>>1; 29 if(x<=mid)insert(lon[rt],lon[o],l,mid,x); 30 else insert(ron[rt],ron[o],mid+1,r,x); 31 } 32 void query(int rt,int o,int l,int r,int x,int y,int &num,LL &sum){ 33 if(x<=l&&r<=y){num+=s1[rt]-s1[o];sum+=s2[rt]-s2[o];return;} 34 int mid=(l+r)>>1; 35 if(x<=mid)query(lon[rt],lon[o],l,mid,x,y,num,sum); 36 if(y>mid)query(ron[rt],ron[o],mid+1,r,x,y,num,sum); 37 } 38 int getpos(int rt,int o,int l,int r,int x,int &sum){ 39 if(l==r)return l; 40 int mid=(l+r)>>1; 41 if(mid<x||(sum+s1[lon[rt]]-s1[lon[o]]>=mid-x+1)){ 42 sum+=s1[lon[rt]]-s1[lon[o]]; 43 return getpos(ron[rt],ron[o],mid+1,r,x,sum); 44 } 45 else return getpos(lon[rt],lon[o],l,mid,x,sum); 46 } 47 int main(){ 48 n=read();m=read(); 49 for(int i=1,x;i<=n;i++){ 50 x=read(); 51 insert(root[i],root[i-1],1,maxn,x); 52 } 53 int l,r,k,num1,num2,pos,cnt; 54 LL ans,sum1,sum2; 55 while(m--){ 56 l=read();r=read();k=read(); 57 ans=0; 58 num1=sum1=num2=sum2=0; 59 if(k>1){ 60 query(root[r],root[l-1],1,maxn,1,k-1,num1,sum1); 61 ans+=1ll*num1*k-sum1+1ll*(num1-1)*num1/2; 62 } 63 if(!num1)pos=k-1; 64 else{ 65 cnt=0; 66 pos=getpos(root[r],root[l-1],1,maxn,k,cnt)-1; 67 } 68 if(k<=pos){ 69 query(root[r],root[l-1],1,maxn,k,pos,num2,sum2); 70 ans+=1ll*pos*num2-sum2-1ll*(num2-1)*num2/2; 71 num2=sum2=0; 72 } 73 query(root[r],root[l-1],1,maxn,pos+1,maxn,num2,sum2); 74 ans+=sum2-1ll*num2*(pos+1)-1ll*(num2-1)*num2/2; 75 printf("%lld\n",ans); 76 } 77 return 0; 78 }
加油加油,gaygay!
CTSC Day1
考試鴿了半小時。。先看T1,我不會??!血量什麼的能夠O(m)維護,那麼查詢呢?對於每一個人單獨算貢獻,因而咱們要算除去他以外的人有i我的存活的機率,貌似O(n3)能夠過70分,而後寫寫寫,寫完過了樣例,沒想着優化,趕忙去看T2,又是貓?又是樹上lca亂搞?wc那題沒改啊,gg了!先寫了暴力分,而後腦子裏忽然想錯題意了,yy了很久仍是失敗了。趕忙去看T3,感受暴搜並無那麼多分,但仍是寫了。GG,70+40+25=135,T2這個照着錯誤的題意想的事好像幹了好多遍了,之後必定要注意。
5.8本身考了一場,全程不在狀態,就寫了點暴力和騙分。貌似三道題都很吊??
CTSC Day2
此次卻是準時進場了。先看T1,裸的log2二分主席樹,寫完沒毛病,過了大樣例,仍是不放心,寫了個暴力對拍。而後看T2,一點不會。看T3,題答,而後開始搞,先搜過了前兩個點,而後第三個點加了好多減枝才搜過去,後來又搞出來了第四個點和第七個點,而後快沒時間了,吧T2的0分暴力寫了很久,還加了一堆減枝,但願有分,最後寫了T3第五個點的dp發現只有3分,我也很無奈啊。最後100+0+58=158,貌似第六個點能夠直接貪心。GG。
5.10又考了一場,全場寫T1,卡T1,寫暴力,沒了。
APIO
先把題目都讀了一遍,發現果真都不可作的樣子,而後先開T3,打算先寫樹的部分分,而後寫了一個多小時,交了若干遍才發現圖有可能不聯通。而後趕忙改了拿到了樹的分,發現鏈的gg了?好吧,可能有環,又寫了,而後去寫T2,原本覺得有很多分都是能夠寫的,後來發現是我想多了。以後又寫了T1的暴力。最後又是照着錯誤的題意去想T1,好不容易寫完了,發現題意又想錯了,最後發現T3的仙人掌部分分很好拿的樣子,然而最後也沒寫完。
12+19+36=67 大概是這個分數吧。
打了兩個ag回來,仍是很不甘心的,尤爲兩場考試中都有很長的時間在想錯誤的題意,我也不知道我是怎麼了,大賽經驗啊。。。
穩住,咱們能贏。
5.16
今天考試整體來講狀態不夠好。今天身體不是很舒服,考試的時候頭也疼,還特別困。
說考試吧,看到三道題,並無發現T2是原題,因而先寫了個點雙,後來發現不對,改爲強聯通份量,而後寫網絡流加反向inf邊的時候纔想起來這道題原來作過,因而又寫了個不縮點的,兩邊拍上了,感受不錯,這時候大概90min了。而後看T1,以爲是一個很噁心的數據結構,又去看T3,數學或是dp的一個計數題,可是感受怎麼寫都須要當前填數的狀態,因而寫了暴力棄掉了,這時候大概還有不到2h。以後去把T1的暴力寫了,以後yy了一個隨機數據跑的很快的騙分,寫上了,兩邊也拍上了,這時候差很少就結束了。最後40+70+50=160,T1騙分就多了10分,T2仍是不清楚題的本質,只記得要加反向邊,卻沒有深刻思考緣由,因而gg,T3暴力多跑了10分,貌似都是50。
關於T3的一點思考:就像題解裏說的:「對排列計數,不可能從左到右填數。」由於一旦這樣,當前所用數的狀態就是不能避免須要記錄的了,因此咱們須要宏觀地來考慮整個過程,好比從小到大來填,這時就須要記錄一些必要的信息:分紅了幾段,兩端點的狀態。可是至少須要的混亂度我以爲仍是比較巧妙或者說是我想不到的,可是這個的確也是必要的,仍是作題少吧,多作題,多思考。。
T1:對於序列維護一個線段樹,支持區間減,求最小值,而後對於左右端點分別維護一個並查集,每一個並查集維護左(右)端點相同的區間,每次刪掉一個區間就在並查集裏切掉一些,而後將他們合併起來,由於每切一個就會合並起來,因此這個的複雜度是O(n)的,線段樹是log的沒有問題。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 300500 7 using namespace std; 8 int n,m,fa1[N],fa2[N],lp[N],rp[N],ll1[N],rr1[N],ll2[N],rr2[N]; 9 int minn[N<<2],lazy[N<<2],pos[N<<2]; 10 int find1(int x){return x==fa1[x]?x:fa1[x]=find1(fa1[x]);} 11 int find2(int x){return x==fa2[x]?x:fa2[x]=find2(fa2[x]);} 12 void change(int rt,int x){ 13 lazy[rt]+=x; 14 minn[rt]-=x; 15 } 16 void pushup(int rt){ 17 if(minn[rt<<1]<=minn[rt<<1|1])minn[rt]=minn[rt<<1],pos[rt]=pos[rt<<1]; 18 else minn[rt]=minn[rt<<1|1],pos[rt]=pos[rt<<1|1]; 19 } 20 void pushdown(int rt){ 21 if(lazy[rt]){ 22 change(rt<<1,lazy[rt]); 23 change(rt<<1|1,lazy[rt]); 24 lazy[rt]=0; 25 } 26 } 27 void build(int rt,int l,int r){ 28 if(l==r){ 29 minn[rt]=rp[l]-lp[l]; 30 pos[rt]=l; 31 return ; 32 } 33 int mid=(l+r)>>1; 34 build(rt<<1,l,mid); 35 build(rt<<1|1,mid+1,r); 36 pushup(rt); 37 } 38 void update(int rt,int l,int r,int x,int y,int z){ 39 if(x<=l&&r<=y){ 40 change(rt,z); 41 return ; 42 } 43 pushdown(rt); 44 int mid=(l+r)>>1; 45 if(x<=mid)update(rt<<1,l,mid,x,y,z); 46 if(y>mid)update(rt<<1|1,mid+1,r,x,y,z); 47 pushup(rt); 48 } 49 void del(int rt,int l,int r,int x){ 50 if(l==r){ 51 minn[rt]=0x7fffffff; 52 pos[rt]=0; 53 return ; 54 } 55 pushdown(rt); 56 int mid=(l+r)>>1; 57 if(x<=mid)del(rt<<1,l,mid,x); 58 else del(rt<<1|1,mid+1,r,x); 59 pushup(rt); 60 } 61 int main(){ 62 scanf("%d%d",&m,&n); 63 for(int i=1;i<=n;i++){ 64 scanf("%d%d",&lp[i],&rp[i]); 65 fa1[i]=fa2[i]=i; 66 ll1[i]=rr1[i]=i; 67 ll2[i]=rr2[i]=i; 68 } 69 build(1,1,n); 70 for(int i=1;i<=n;i++){ 71 int p=pos[1]; 72 printf("%d\n",p); 73 int l=lp[find1(p)],r=rp[find2(p)]; 74 for(int j=p+1;j<=n&&lp[find1(j)]<r;j=rr1[find1(j)]+1){ 75 update(1,1,n,ll1[find1(j)],rr1[find1(j)],r-lp[find1(j)]); 76 int nr=rr1[find1(j)]; 77 fa1[find1(j)]=find1(p+1); 78 ll1[find1(j)]=p+1;rr1[find1(j)]=nr; 79 lp[find1(j)]=r; 80 } 81 for(int j=p-1;j&&rp[find2(j)]>l;j=ll2[find2(j)]-1){ 82 update(1,1,n,ll2[find2(j)],rr2[find2(j)],rp[find2(j)]-l); 83 int nl=ll2[find2(j)]; 84 fa2[find2(j)]=find2(p-1); 85 rr2[find2(j)]=p-1;ll2[find2(j)]=nl; 86 rp[find2(j)]=l; 87 } 88 del(1,1,n,p); 89 } 90 return 0; 91 }
T2,網絡流,這裏要注意加反向邊的時候必定要保證這條邊能被到達。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 #include <queue> 8 #define inf 2333333333333ll 9 #define N 102 10 #define LL long long 11 using namespace std; 12 int q[N],he,ta,n,m; 13 int e=2,head[N]; 14 struct edge{ 15 int u,v,next; 16 LL f; 17 }ed[5005]; 18 void add(int u,int v,LL f){ 19 ed[e].u=u;ed[e].v=v;ed[e].f=f; 20 ed[e].next=head[u];head[u]=e++; 21 ed[e].u=v;ed[e].v=u;ed[e].f=0; 22 ed[e].next=head[v];head[v]=e++; 23 } 24 int dep[N],S,T; 25 bool bfs(){ 26 memset(dep,0,sizeof dep); 27 dep[S]=1;he=ta=1;q[1]=S; 28 while(he<=ta){ 29 int x=q[he++]; 30 for(int i=head[x];i;i=ed[i].next){ 31 if(ed[i].f&&!dep[ed[i].v]){ 32 dep[ed[i].v]=dep[x]+1; 33 if(ed[i].v==T)return 1; 34 q[++ta]=ed[i].v; 35 } 36 } 37 } 38 return 0; 39 } 40 LL dfs(int x,LL f){ 41 if(x==T||!f)return f; 42 LL ans=0; 43 for(int i=head[x];i;i=ed[i].next){ 44 if(ed[i].f&&dep[ed[i].v]==dep[x]+1){ 45 LL nxt=dfs(ed[i].v,min(f,ed[i].f)); 46 ans+=nxt,f-=nxt,ed[i].f-=nxt,ed[i^1].f+=nxt; 47 if(!f)break; 48 } 49 } 50 if(!ans)dep[x]=-2; 51 return ans; 52 } 53 LL dinic(){ 54 LL ans=0; 55 while(bfs())ans+=dfs(S,inf); 56 if(!ans||ans>=inf)return -1; 57 return ans; 58 } 59 bool vis[N]; 60 void dfs(int x){ 61 vis[x]=1; 62 for(int i=head[x];i;i=ed[i].next)if(!(i&1)){ 63 ed[i^1].f=inf; 64 if(!vis[ed[i].v])dfs(ed[i].v); 65 } 66 } 67 int main(){ 68 scanf("%d%d",&n,&m); 69 LL w; 70 for(int i=1,u,v;i<=m;i++){ 71 scanf("%d%d%lld",&u,&v,&w); 72 add(++u,++v,w); 73 } 74 S=1;T=n; 75 dfs(S); 76 printf("%lld\n",dinic()); 77 return 0; 78 }
T3,很優秀的一個dp,咱們考慮從小到大填,須要記錄的有當前的段數,兩端點的狀態以及把它填平須要的混亂度。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define mod 1000000007 7 using namespace std; 8 int n,m,ans,a[105],f[2][105][1005][3]; 9 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 10 int main(){ 11 scanf("%d%d",&n,&m); 12 if(n==1){ 13 puts("1"); 14 return 0; 15 } 16 for(int i=1;i<=n;i++) 17 scanf("%d",&a[i]); 18 sort(a+1,a+n+1); 19 f[1][1][0][0]=1; 20 f[1][1][0][1]=2; 21 int ii=1; 22 for(int i=2;i<=n;i++){ 23 ii^=1; 24 memset(f[ii],0,sizeof f[ii]); 25 for(int j=1;j<i;j++){ 26 for(int k=0;k<=m;k++){ 27 for(int l=0;l<=2;l++){ 28 int w=k+(a[i]-a[i-1])*(2*j-l),ff=f[ii^1][j][k][l]; 29 if(!ff)continue; 30 if(w>m)continue; 31 if(l<2){ 32 UPD(f[ii][j][w][l+1],1ll*ff*(2-l)%mod); 33 UPD(f[ii][j+1][w][l+1],1ll*ff*(2-l)%mod); 34 } 35 UPD(f[ii][j-1][w][l],1ll*ff*(j-1)%mod); 36 UPD(f[ii][j+1][w][l],1ll*ff*(j-1+(2-l))%mod); 37 UPD(f[ii][j][w][l],1ll*ff*(2*j-l)%mod); 38 } 39 } 40 } 41 } 42 for(int i=0;i<=m;i++)UPD(ans,f[ii][1][i][2]); 43 printf("%d\n",ans); 44 return 0; 45 }
加油!!!
5.17
pku的acm模擬賽
先看A,字符串匹配的題,要求是反迴文,有點意思,好像可作。而後看B,一看就是數據結構碼農題,棄棄棄。C是個數學題?而後發現D是個簽到題,趕忙水了過去,E是個指望?F是個樹形dp?G是個dp或網絡流?而後在我決定作哪一個題的時候,發現lc C題A了??趕忙去看,寫了個複雜度不對的暴力,交,A了???而後發現一堆人都水過去了,0ms,0kb?我猜沒有測試點,而後加上測試點以後,hzoi全員fst,那不行啊,想,死磕,發現這個和縮進優化同樣直接處理個前綴和就好了,而後寫,wa?沒加case,加上A了,而後去想G的dp,寫了寫發現不可寫,而後又去想F,狀態定義也不太清楚,又推了推E的式子,挺像fft的,可是模數不對,複雜度也不對,就沒接着搞,最後又去想了想A,也沒想出來。
兩道題,不夠啊。。
A,對於每一個串,咱們首先把原串和反着的反串插進AC自動機,如001就插入001和011,而後還要再處理一個狀態就是中間若是出現這個串原串也能匹配上,001的話咱們還要插入00,這樣直接在AC自動機上dp就能夠了,最後一步要特殊轉移。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define N 333 8 #define mod 998244353 9 using namespace std; 10 char s[22]; 11 int T,n,m,ans,root,sz,q[N],he,ta; 12 int ch[N][2],fail[N],st1[N],st2[N],f[105][N][1<<6|1]; 13 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 14 void insert(char *s,int id){ 15 int len=strlen(s); 16 int now; 17 for(int i=0;len-i>=i;i++){ 18 bool flag=1; 19 for(int j=i-1;~j;j--) 20 if(s[j]==s[(i)+(i-1-j)]){flag=0;break;} 21 if(flag){ 22 now=root; 23 for(int j=len-1;j>=i;j--){ 24 int t=(s[j]-'0')^1; 25 if(!ch[now][t])ch[now][t]=++sz; 26 now=ch[now][t]; 27 } 28 st2[now]|=(1<<id-1); 29 if(!i)st1[now]|=(1<<id-1); 30 } 31 } 32 for(int i=len-1;len-1-i<i+1;i--){ 33 bool flag=1; 34 for(int j=i+1;j<len;j++) 35 if(s[j]==s[(i)-(j-i-1)]){flag=0;break;} 36 if(flag){ 37 now=root; 38 for(int j=0;j<=i;j++){ 39 int t=s[j]-'0'; 40 if(!ch[now][t])ch[now][t]=++sz; 41 now=ch[now][t]; 42 } 43 st2[now]|=(1<<id-1); 44 if(i==len-1)st1[now]|=(1<<id-1); 45 } 46 } 47 } 48 int main(){ 49 scanf("%d",&T); 50 while(T--){ 51 scanf("%d%d",&n,&m); 52 root=sz=1; 53 memset(ch,0,sizeof ch); 54 memset(st1,0,sizeof st1); 55 memset(st2,0,sizeof st2); 56 for(int i=1;i<=n;i++){ 57 scanf("%s",s); 58 insert(s,i); 59 } 60 ch[0][0]=ch[0][1]=1; 61 he=ta=1;q[1]=1;fail[1]=0; 62 while(he<=ta){ 63 int x=q[he++]; 64 for(int i=0;i<2;i++){ 65 if(ch[x][i]){ 66 fail[ch[x][i]]=ch[fail[x]][i]; 67 q[++ta]=ch[x][i]; 68 } 69 else ch[x][i]=ch[fail[x]][i]; 70 } 71 st1[x]|=st1[fail[x]]; 72 st2[x]|=st2[fail[x]]; 73 } 74 memset(f,0,sizeof f); 75 f[0][1][0]=1; 76 for(int i=1;i<m;i++){ 77 for(int j=1;j<=sz;j++){ 78 for(int k=0;k<(1<<n);k++)if(f[i-1][j][k]){ 79 UPD(f[i][ch[j][0]][k|st1[ch[j][0]]],f[i-1][j][k]); 80 UPD(f[i][ch[j][1]][k|st1[ch[j][1]]],f[i-1][j][k]); 81 } 82 } 83 } 84 for(int i=1;i<=sz;i++){ 85 for(int j=0;j<(1<<n);j++)if(f[m-1][i][j]){ 86 UPD(f[m][ch[i][0]][j|st1[ch[i][0]]|st2[ch[i][0]]],f[m-1][i][j]); 87 UPD(f[m][ch[i][1]][j|st1[ch[i][1]]|st2[ch[i][1]]],f[m-1][i][j]); 88 } 89 } 90 ans=0; 91 for(int i=1;i<=sz;i++)if(f[m][i][(1<<n)-1]) 92 UPD(ans,f[m][i][(1<<n)-1]); 93 printf("%d\n",ans); 94 } 95 return 0; 96 }
B,由於一個可能重複拼在一塊兒,因此咱們要可持久化平衡樹,可是咱們仍是無法快速把一個區間複製屢次,因而咱們考慮快速冪(倍增),注意要回收空間。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 200500 7 #define LL long long 8 using namespace std; 9 int n,m,a[N],tot,cnt; 10 #define tp pair<Treap*,Treap*> 11 struct Treap{ 12 Treap *ch[2]; 13 int size,val; 14 LL sum; 15 void pushup(){ 16 sum=ch[0]->sum+ch[1]->sum+val; 17 size=ch[0]->size+ch[1]->size+1; 18 } 19 }*null,*org,*root,mem[N<<5]; 20 Treap * newTreap(int v){ 21 Treap *rt=mem+(++tot); 22 rt->ch[0]=rt->ch[1]=null; 23 rt->size=1;rt->val=rt->sum=v; 24 } 25 Treap * copy(Treap *x){ 26 Treap *rt=mem+(++tot); 27 *rt=*x;return rt; 28 } 29 tp split(Treap *o,int k){ 30 if(o==null)return tp(null,null); 31 Treap *rt=copy(o); 32 tp x; 33 if(o->ch[0]->size>=k){ 34 x=split(rt->ch[0],k); 35 rt->ch[0]=x.second; 36 rt->pushup(); 37 x.second=rt; 38 } 39 else{ 40 x=split(rt->ch[1],k-o->ch[0]->size-1); 41 rt->ch[1]=x.first; 42 rt->pushup(); 43 x.first=rt; 44 } 45 return x; 46 } 47 Treap * merge(Treap *a,Treap *b){ 48 if(a==null)return b; 49 if(b==null)return a; 50 if(rand()%(a->size+b->size)<a->size){ 51 Treap *rt=copy(a); 52 rt->ch[1]=merge(rt->ch[1],b); 53 rt->pushup(); 54 return rt; 55 } 56 else{ 57 Treap *rt=copy(b); 58 rt->ch[0]=merge(a,rt->ch[0]); 59 rt->pushup(); 60 return rt; 61 } 62 } 63 void travel(Treap *rt){ 64 if(rt==null)return ; 65 travel(rt->ch[0]); 66 a[++cnt]=rt->val; 67 travel(rt->ch[1]); 68 } 69 Treap * build(int l,int r){ 70 if(l>r)return null; 71 int mid=(l+r)>>1; 72 Treap *rt=newTreap(a[mid]); 73 rt->ch[0]=build(l,mid-1); 74 rt->ch[1]=build(mid+1,r); 75 rt->pushup(); 76 return rt; 77 } 78 void rebuild(){ 79 tot=n;cnt=0; 80 travel(root); 81 root=build(1,n); 82 } 83 LL query(int x){ 84 Treap *now=root; 85 LL ans=0; 86 while(1){ 87 if(now==null)return ans; 88 if(now->ch[0]->size>=x)now=now->ch[0]; 89 else ans+=now->ch[0]->sum+now->val,x-=now->ch[0]->size+1,now=now->ch[1]; 90 } 91 } 92 Treap * qp (Treap *a,int b){ 93 Treap *c=null; 94 for(;b;b>>=1,a=merge(a,a)) 95 if(b&1)c=merge(c,a); 96 return c; 97 } 98 void work(int l,int r){ 99 int k;scanf("%d",&k); 100 tp x=split(root,l-1); 101 tp y=split(x.second,r-l+1); 102 tp z=split(x.first,l-k-1); 103 tp w=split(z.second,(r-l+1)%k); 104 Treap *rt=qp(z.second,(r-l+1)/k); 105 rt=merge(rt,w.first); 106 root=merge(merge(x.first,rt),y.second); 107 if((N<<5)-tot<1000)rebuild(); 108 } 109 void update(int l,int r){ 110 tp x=split(root,l-1); 111 tp y=split(x.second,r-l+1); 112 tp z=split(org,l-1); 113 tp w=split(z.second,r-l+1); 114 root=merge(merge(x.first,w.first),y.second); 115 if((N<<5)-tot<1000)rebuild(); 116 } 117 int main(){ 118 null=mem; 119 null->ch[0]=null->ch[1]=null; 120 null->size=null->val=null->sum=0; 121 scanf("%d%d",&n,&m); 122 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 123 root=org=build(1,n); 124 int o,l,r; 125 while(m--){ 126 scanf("%d%d%d",&o,&l,&r); 127 if(o==1)printf("%lld\n",query(r)-query(l-1)); 128 if(o==2)work(l,r); 129 if(o==3)update(l,r); 130 } 131 return 0; 132 }
C,咱們要的是$\sum_{i=1}^{mx}{(-\mu{(i)}) \cdot \prod_{j=1}^{n}{ \lfloor {\frac{a_{j}}{i}} \rfloor}}$ ,直接預處理前綴和而後調和級數。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define mod 1000000007 7 #define N 100500 8 using namespace std; 9 int mu[N],prime[N],vis[N],tot; 10 int T,n,ans,mn,mx,s[N],a[N]; 11 void init(){ 12 mu[1]=1; 13 for(int i=2;i<=100000;i++){ 14 if(!vis[i]){ 15 prime[++tot]=i; 16 mu[i]=-1; 17 } 18 for(int j=1;j<=tot&&i*prime[j]<=100000;j++){ 19 vis[i*prime[j]]=1; 20 if(i%prime[j]==0){ 21 mu[i*prime[j]]=0; 22 break; 23 } 24 mu[i*prime[j]]=-mu[i]; 25 } 26 } 27 } 28 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 29 int qp(int a,int b){ 30 int c=1; 31 for(;b;b>>=1,a=1ll*a*a%mod) 32 if(b&1)c=1ll*c*a%mod; 33 return c; 34 } 35 int main(){ 36 init(); 37 scanf("%d",&T); 38 for(int ca=1;ca<=T;ca++){ 39 scanf("%d",&n); 40 mn=0x3fffffff;mx=0; 41 memset(s,0,sizeof s); 42 for(int i=1;i<=n;i++){ 43 scanf("%d",&a[i]); 44 mn=min(mn,a[i]); 45 mx=max(mx,a[i]); 46 s[a[i]]++; 47 } 48 for(int i=1;i<=mx;i++)s[i]=s[i-1]+s[i]; 49 ans=0; 50 for(int i=2,now,j;i<=mn;i++)if(mu[i]){ 51 for(now=j=1;j*i<=mx;j++) 52 now=1ll*now*qp(j,s[min(mx,(j+1)*i-1)]-s[j*i-1])%mod; 53 if(mu[i]<0)UPD(ans,now); 54 else UPD(ans,mod-now); 55 } 56 printf("Case #%d: %d\n",ca,ans); 57 } 58 return 0; 59 }
D,簽到題,亂判就行。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 int T,bo[10],x[10]; 8 char s[10][30]; 9 int getnum(int x){ 10 bo[1]=(s[1][x+1]=='X'); 11 bo[2]=(s[2][x]=='X'); 12 bo[3]=(s[2][x+3]=='X'); 13 bo[4]=(s[4][x+1]=='X'); 14 bo[5]=(s[5][x]=='X'); 15 bo[6]=(s[5][x+3]=='X'); 16 bo[7]=(s[7][x+1]=='X'); 17 if((bo[1])&&(bo[2])&&(bo[3])&&(!bo[4])&&(bo[5])&&(bo[6])&&(bo[7]))return 0; 18 if((!bo[1])&&(!bo[2])&&(bo[3])&&(!bo[4])&&(!bo[5])&&(bo[6])&&(!bo[7]))return 1; 19 if((bo[1])&&(!bo[2])&&(bo[3])&&(bo[4])&&(bo[5])&&(!bo[6])&&(bo[7]))return 2; 20 if((bo[1])&&(!bo[2])&&(bo[3])&&(bo[4])&&(!bo[5])&&(bo[6])&&(bo[7]))return 3; 21 if((!bo[1])&&(bo[2])&&(bo[3])&&(bo[4])&&(!bo[5])&&(bo[6])&&(!bo[7]))return 4; 22 if((bo[1])&&(bo[2])&&(!bo[3])&&(bo[4])&&(!bo[5])&&(bo[6])&&(bo[7]))return 5; 23 if((bo[1])&&(bo[2])&&(!bo[3])&&(bo[4])&&(bo[5])&&(bo[6])&&(bo[7]))return 6; 24 if((bo[1])&&(!bo[2])&&(bo[3])&&(!bo[4])&&(!bo[5])&&(bo[6])&&(!bo[7]))return 7; 25 if((bo[1])&&(bo[2])&&(bo[3])&&(bo[4])&&(bo[5])&&(bo[6])&&(bo[7]))return 8; 26 if((bo[1])&&(bo[2])&&(bo[3])&&(bo[4])&&(!bo[5])&&(bo[6])&&(bo[7]))return 9; 27 } 28 int main(){ 29 scanf("%d",&T); 30 while(T--){ 31 for(int i=1;i<=7;i++) 32 scanf("%s",s[i]); 33 x[1]=getnum(0); 34 x[2]=getnum(5); 35 x[3]=getnum(12); 36 x[4]=getnum(17); 37 printf("%d%d:%d%d\n",x[1],x[2],x[3],x[4]); 38 } 39 }
E,化完式子是$3^{n} \cdot {\sum_{d=1}^{n} { \phi{(d)} \sum_{i=1}^{ \lfloor {\frac{n}{d}} \rfloor} } \sum_{j=1}^{ \lfloor {\frac{n}{d}} \rfloor - i} C_{n}^{id} \cdot C_{n-id}^{jd} }$
而後就能夠愉快的任意模數FFT了,代碼咕咕咕了555。對於任意模數fft能夠看這裏
F題就是一個樹形dp,可是狀態的確很難想到,關鍵的一維0和1表明當前點是否必定在這個最大匹配裏,別的套路轉移就好,轉移時還要考慮這條邊是否刪去。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define mod 998244353 8 #define N 50005 9 using namespace std; 10 int e,head[N]; 11 struct edge{ 12 int v,next; 13 }ed[N<<1]; 14 void add(int u,int v){ 15 ed[e].v=v; 16 ed[e].next=head[u]; 17 head[u]=e++; 18 } 19 void UPD(int &a,int b){ 20 a=(a+b>=mod)?(a+b-mod):(a+b); 21 } 22 int T,n,m,size[N],f[N][205][2],g[405][2]; 23 void dfs(int x,int fa){ 24 size[x]=1; 25 f[x][0][0]=1; 26 for(int i=head[x];i;i=ed[i].next){ 27 int v=ed[i].v; 28 if(v==fa)continue; 29 dfs(v,x); 30 memset(g,0,sizeof g); 31 for(int j=0;j<=size[x];j++){ 32 if(!f[x][j][0]&&!f[x][j][1])continue; 33 for(int k=0;k<=size[v];k++){ 34 UPD(g[j+k][0],1ll*f[x][j][0]*f[v][k][0]%mod); 35 UPD(g[j+k+1][1],1ll*f[x][j][0]*f[v][k][0]%mod); 36 UPD(g[j+k][0],2ll*f[x][j][0]*f[v][k][1]%mod); 37 UPD(g[j+k][1],2ll*f[x][j][1]*(f[v][k][0]+f[v][k][1])%mod); 38 } 39 } 40 size[x]=min(m-1,size[x]+size[v]); 41 for(int j=0;j<=size[x];j++){ 42 f[x][j][0]=(g[j][0]+g[j+m][0])%mod; 43 f[x][j][1]=(g[j][1]+g[j+m][1])%mod; 44 } 45 } 46 } 47 int main(){ 48 scanf("%d",&T); 49 while(T--){ 50 e=1;memset(head,0,sizeof head); 51 scanf("%d%d",&n,&m); 52 for(int i=1,u,v;i<n;i++){ 53 scanf("%d%d",&u,&v); 54 add(u,v);add(v,u); 55 } 56 memset(f,0,sizeof f); 57 dfs(1,0); 58 printf("%d\n",(f[1][0][0]+f[1][0][1])%mod); 59 } 60 return 0; 61 }
G,又是wqs二分,我又沒有想到,想斜率,斜率,斜率。二分減去的權值,而後作最小匹配並記錄邊數就行了。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define LL long long 8 #define N 40050 9 #define inf 0x3f3f3f3f3f3f3f3f 10 using namespace std; 11 char B[1<<15],*S=B,*T=B; 12 #define getc (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++) 13 inline int read() 14 { 15 int x=0;char ch=getc; 16 while(ch<'0'|ch>'9')ch=getc; 17 while(ch>='0'&ch<='9')x=10*x+(ch^48),ch=getc; 18 return x; 19 } 20 int a[N][6],b[N][6],n,m,K,Tim; 21 int g[2][33],now,last,num; 22 LL f[2][33],Ans,ans; 23 void dp(int i,int j,LL v){ 24 now^=1;last^=1; 25 memset(f[now],0x3f,sizeof f[now]); 26 f[now][0]=g[now][0]=0; 27 for(register int k=0,x,y,nk;k<(1<<m+1);++k)if(f[last][k]<inf){ 28 x=(k>>j-1)&1,y=(k>>j)&1; 29 LL nf=f[last][k],ng=g[last][k]; 30 if(x&&y)continue; 31 if(x){ 32 nk=k^(1<<j-1); 33 if(nf<f[now][nk]||(nf==f[now][nk]&&ng>g[now][nk])) 34 f[now][nk]=nf,g[now][nk]=ng; 35 } 36 else if(y){ 37 nk=k^(1<<j); 38 if(nf<f[now][nk]||(nf==f[now][nk]&&ng>g[now][nk])) 39 f[now][nk]=nf,g[now][nk]=ng; 40 } 41 else if(!x&&!y){ 42 if(i<n){ 43 nk=k^(1<<j-1); 44 if(nf+a[i][j]-v<f[now][nk]||(nf+a[i][j]-v==f[now][nk]&&ng+1>g[now][nk])) 45 f[now][nk]=nf+a[i][j]-v,g[now][nk]=ng+1; 46 } 47 if(j<m){ 48 nk=k^(1<<j); 49 if(nf+b[i][j]-v<f[now][nk]||(nf+b[i][j]-v==f[now][nk]&&ng+1>g[now][nk])) 50 f[now][nk]=nf+b[i][j]-v,g[now][nk]=ng+1; 51 } 52 if(nf<f[now][k]||(nf==f[now][k]&&ng>g[now][k])) 53 f[now][k]=nf,g[now][k]=ng; 54 } 55 } 56 } 57 bool work(LL x){ 58 now=0;last=1; 59 memset(f[now],0x3f,sizeof f[now]); 60 memset(g,0,sizeof g); 61 f[now][0]=g[now][0]=0; 62 for(int i=1;i<=n;++i){ 63 for(int j=1;j<=m;++j) 64 dp(i,j,x); 65 for(int j=(1<<m+1)-1;~j;--j){ 66 if(j&1)f[now][j]=inf,g[now][j]=0; 67 else f[now][j]=f[now][j>>1],g[now][j]=g[now][j>>1]; 68 } 69 } 70 ans=inf; 71 for(int i=0;i<(1<<m);i++) 72 if(f[now][i]<ans){ans=f[now][i],num=g[now][i];} 73 Ans=ans; 74 return num>=K; 75 } 76 int main(){ 77 scanf("%d",&Tim); 78 while(Tim--){ 79 n=read();m=read();K=read(); 80 for(int i=1;i<n;++i) 81 for(int j=1;j<=m;++j)a[i][j]=read(); 82 for(int i=1;i<=n;++i) 83 for(int j=1;j<m;++j)b[i][j]=read(); 84 LL l=1,r=1e14,mid,fin=0; 85 while(l<=r){ 86 mid=(2*l+r)/3; 87 if(work(mid))fin=mid,r=mid-1; 88 else l=mid+1; 89 } 90 work(fin); 91 printf("%lld\n",Ans+fin*K); 92 } 93 }
水平不行啊。
5.18
今天的話。前兩個小時都在推T2的式子,後來推出來30分了,寫上了,不過很是慢。又卡了卡常。以後看了看T1,感受兩個部分分均可以作,可是都沒有寫,看了看T3,不會。而後糾結去幹T1仍是T3,然而我樹上莫隊並不太會,鏈上的推的式子也很噁心,因而最後去想T3,而後發現是道水題,趕忙寫了,由於方便,就先用int寫了,沒開long long,最後還剩2min的時候拍上了,趕忙把int都改爲了long long結果inf沒有改,就gg了。0+20+30=50。
T3,發現每一個點必定和他第k+1個祖先顏色相同,因而把樹縮上去以後dp就行了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define LL long long 7 #define inf 0x3fffffffffffffff 8 #define N 2050 9 using namespace std; 10 int T,up,n,K,m; 11 int a[10000005],b[10000005],pp[10000005]; 12 LL f[N][205],s[N][205],ned[N][205],g[205]; 13 namespace Read{ 14 unsigned int SA, SB, SC;int p, A, B; 15 unsigned int rng61(){ 16 SA ^= SA << 16; 17 SA ^= SA >> 5; 18 SA ^= SA << 1; 19 unsigned int t = SA; 20 SA = SB; 21 SB = SC; 22 SC ^= t ^ SA; 23 return SC; 24 } 25 void gen(){ 26 scanf("%d%d%d%d%u%u%u%d%d", &n, &K, &m, &p, &SA, &SB, &SC, &A, &B); 27 for(int i = 1; i <= p; i++)scanf("%d%d", &a[i], &b[i]); 28 for(int i = p + 1; i <= n; i++){ 29 a[i] = rng61() % A + 1; 30 b[i] = rng61() % B + 1; 31 } 32 } 33 } 34 bool dfs(int x){ 35 if((x<<1)>up&&(x<(1<<K))){ 36 memset(f[x],0,sizeof f[x]); 37 return 0; 38 } 39 if((x<<1)>up){ 40 for(int i=0;i<m;i++)f[x][i]=ned[x][i]; 41 return 1; 42 } 43 bool bo=0; 44 if((x<<1)<=up)bo|=dfs(x<<1); 45 if((x<<1|1)<=up)bo|=dfs(x<<1|1); 46 for(int i=0;i<m;i++)g[i]=0; 47 if((x<<1)<=up)for(int i=0;i<m;i++)g[i]+=f[x<<1][i]; 48 if((x<<1|1)<=up)for(int i=0;i<m;i++)g[i]+=f[x<<1|1][i]; 49 if(x>=(1<<K))bo=1; 50 if(!bo){ 51 memset(f[x],0,sizeof f[x]); 52 return 0; 53 } 54 for(int i=0;i<m;i++){ 55 f[x][i]=inf; 56 for(int j=0;j<m;j++) 57 f[x][i]=min(f[x][i],g[j]+ned[x][(i-j+m)%m]); 58 } 59 return 1; 60 } 61 int main(){ 62 //freopen("test.in","r",stdin); 63 scanf("%d",&T); 64 while(T--){ 65 Read::gen(); 66 up=min(n,(1<<K+1)-1); 67 memset(s,0,sizeof s); 68 for(int i=1;i<=up;i++)pp[i]=i,s[i][a[i]%m]+=b[i]; 69 for(int i=(1<<K+1);i<=n;i++){ 70 pp[i]=pp[i>>(K+1)]; 71 s[pp[i]][a[i]%m]+=b[i]; 72 } 73 for(int i=1;i<=up;i++){ 74 for(int j=0;j<m;j++){ 75 ned[i][j]=0; 76 for(int k=0;k<m;k++) 77 ned[i][j]+=s[i][k]*((j-k+m)%m); 78 } 79 } 80 dfs(1); 81 printf("%lld\n",f[1][0]); 82 } 83 }
保持思考。
5.19
心情很差不想寫了怎麼辦。。
5.20
仍是寫寫吧。
首先是昨天的IOI賽制,看完T1,並不難想,但很不想寫,看T2,割點裸題?yy了一下好像要用圓方樹,但我仍是不會,而後看T3,貌似不是很難推。而後先去看T3,寫了幾個式子都不對,有點難搞,這時候發現WQ把T2A了??!抉擇了一下決定去寫T2,寫了1h寫完了個假的圓方樹,結果過不了第二個樣例,而後yy了一下,搞了種相似縮點的打法,過了,交!A了。而後接着去看T3,感受有規律,最後打出來了個表,要分解質因數,而後沒時間了。0+100+0=100 rank2。
題解一會補。
T2,裸的圓方樹+虛樹。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 #define N 200500 8 #define pb push_back 9 using namespace std; 10 int e=1,head[N]; 11 struct edge{ 12 int v,next; 13 }ed[N<<1]; 14 void add(int u,int v){ 15 ed[e].v=v; 16 ed[e].next=head[u]; 17 head[u]=e++; 18 } 19 vector <int> V[N]; 20 int n,m,qr,T,K,ans,q[N],tim; 21 int dfn[N],low[N],top,sta[N],root,son,ge[N],tot; 22 void tarjan(int x){ 23 dfn[x]=low[x]=++tim; 24 sta[++top]=x; 25 for(int i=0;i<V[x].size();i++){ 26 int v=V[x][i]; 27 if(dfn[v]){ 28 low[x]=min(low[x],dfn[v]); 29 continue; 30 } 31 tarjan(v); 32 low[x]=min(low[x],low[v]); 33 if(dfn[x]<=low[v]){ 34 int y;tot++; 35 do{ 36 y=sta[top--]; 37 add(y,n+tot); 38 add(n+tot,y); 39 }while(y!=v); 40 add(x,n+tot); 41 add(n+tot,x); 42 if(x==root)son++; 43 else ge[x]=1; 44 } 45 } 46 } 47 int fa[N],dep[N],val[N],s[N],seq[N<<1],num,pos[N],mn[N<<1][20],lg[N<<1]; 48 void dfs(int x){ 49 dep[x]=dep[fa[x]]+1; 50 s[x]=s[fa[x]]+val[x]; 51 seq[++num]=x;pos[x]=num; 52 for(int i=head[x];i;i=ed[i].next){ 53 int v=ed[i].v; 54 if(v==fa[x])continue; 55 fa[v]=x;dfs(v); 56 seq[++num]=x; 57 } 58 } 59 int Min(int x,int y){return dep[x]<dep[y]?x:y;} 60 void st_init(){ 61 for(int i=1,j=1,cnt=0;i<=num;i++){ 62 if(i>(j<<1))j<<=1,cnt++; 63 lg[i]=cnt; 64 } 65 for(int i=1;i<=num;i++)mn[i][0]=seq[i]; 66 for(int i=1;i<=lg[num];i++) 67 for(int j=1;j+(1<<i)-1<=num;j++) 68 mn[j][i]=Min(mn[j][i-1],mn[j+(1<<i-1)][i-1]); 69 } 70 int getlca(int x,int y){ 71 x=pos[x];y=pos[y]; 72 if(x>y)swap(x,y); 73 int k=lg[y-x+1]; 74 return Min(mn[x][k],mn[y-(1<<k)+1][k]); 75 } 76 bool cmp(int a,int b){ 77 return pos[a]<pos[b]; 78 } 79 int getans(int x,int y){ 80 if(!y)return 0; 81 return s[y]-s[x]; 82 } 83 void init(){ 84 for(int i=1;i<=n;i++)V[i].clear(); 85 e=1;memset(head,0,sizeof head); 86 top=tim=tot=num=0; 87 memset(ge,0,sizeof ge); 88 memset(fa,0,sizeof fa); 89 memset(val,0,sizeof val); 90 memset(dfn,0,sizeof dfn); 91 } 92 int main(){ 93 scanf("%d",&T); 94 while(T--){ 95 scanf("%d%d",&n,&m); 96 init(); 97 for(int i=1,u,v;i<=m;i++){ 98 scanf("%d%d",&u,&v); 99 V[u].pb(v),V[v].pb(u); 100 } 101 root=1;son=0; 102 tarjan(1); 103 if(son>=2)ge[1]=1; 104 for(int i=1;i<=n;i++)if(ge[i])val[i]=1; 105 dfs(1); 106 st_init(); 107 scanf("%d",&qr); 108 while(qr--){ 109 scanf("%d",&K); 110 ans=0; 111 for(int i=1;i<=K;i++){ 112 scanf("%d",&q[i]); 113 if(ge[q[i]])ans--; 114 } 115 sort(q+1,q+K+1,cmp); 116 sta[1]=q[1];top=1; 117 for(int i=2;i<=K;i++){ 118 int a=q[i],b=getlca(q[i],sta[top]),c=0; 119 while(dep[sta[top]]>dep[b]) 120 ans+=getans(sta[top],c),c=sta[top--]; 121 ans+=getans(b,c); 122 if(sta[top]!=b)sta[++top]=b; 123 sta[++top]=a; 124 } 125 while(top>1)ans+=getans(sta[top-1],sta[top]),top--; 126 ans+=val[sta[1]]; 127 printf("%d\n",ans); 128 } 129 } 130 return 0; 131 }
T3,首先咱們設$f[i]$爲最小循環節爲i的方案數,能夠發現$\sum_{d|m}{f[d]}=k^{ \lceil \frac{m}{2} \rceil }$,而後推一推式子就行了,其實挺麻煩的,不如打表,可是作法都是同樣的,要分解質因數。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define int long long 7 using namespace std; 8 int n,m,K,ans,mod,T; 9 int p[55],cnt,mi[55],pk[55][66]; 10 int R(int x){ 11 return rand()*rand()%x; 12 } 13 int mul(int a,int b,int p){ 14 return (a*b-(int)(((long double)a*b+0.5)/p)*p+p)%p; 15 } 16 int qp(int a,int b,int c){ 17 int ans=1; 18 for(;b;b>>=1,a=mul(a,a,c)) 19 if(b&1)ans=mul(ans,a,c); 20 return ans; 21 } 22 int prime[10]={0,2,3,5,7,11}; 23 bool miller_rabin(int x){ 24 if(x==1)return 0; 25 for(int i=1;i<=5;i++)if(x==prime[i])return 1; 26 for(int i=1;i<=5;i++)if(x%prime[i]==0)return 0; 27 int y=x-1,cnt=0; 28 while(!(y&1))y>>=1,cnt++; 29 for(int i=1;i<=5;i++){ 30 int now=qp(prime[i],y,x),nxt; 31 for(int j=1;j<=cnt;j++){ 32 nxt=mul(now,now,x); 33 if(nxt==1&&now!=1&&now!=x-1)return 0; 34 now=nxt; 35 } 36 if(nxt!=1)return 0; 37 } 38 return 1; 39 } 40 int gcd(int a,int b){return !b?a:gcd(b,a%b);} 41 int pollard_rho(int x,int y){ 42 int c=R(x-1)+1,d=c,g=1; 43 for(int i=1,j=2;g==1;i++){ 44 c=(mul(c,c,x)+y)%x; 45 g=gcd(abs(c-d),x); 46 if(i==j)d=c,j<<=1; 47 } 48 return g; 49 } 50 void divide(int x){ 51 if(x==1)return ; 52 if(miller_rabin(x)){ 53 p[++cnt]=x; 54 return ; 55 } 56 int now=x; 57 while(now==x)now=pollard_rho(x,R(x-1)); 58 divide(now); 59 divide(x/now); 60 } 61 int getg(int x){ 62 return qp(K,(x+1)/2,mod); 63 } 64 int geth(int x){ 65 return (x&1?x:(x>>1))%mod; 66 } 67 void UPD(int &a,int b){ 68 a=(a+b>=mod)?(a+b-mod):(a+b); 69 } 70 void dfs(int x,int d,int now){ 71 if(x==m+1){ 72 if((d&1)&&(!((n/d)&1)))return; 73 //printf("d==%lld n/d==%lld now==%lld g=%lld h=%lld\n",d,n/d,now,getg(d),geth(d)); 74 UPD(ans,getg(d)*geth(d)%mod*(now%mod+mod)%mod); 75 return ; 76 } 77 for(int i=0;i<=mi[x];i++) 78 dfs(x+1,d*pk[x][i],(i==mi[x])?now:now*(1-p[x])); 79 } 80 signed main(){ 81 scanf("%lld",&T); 82 while(T--){ 83 scanf("%lld%lld%lld",&n,&K,&mod);K%=mod; 84 cnt=0; 85 divide(n); 86 sort(p+1,p+cnt+1); 87 m=0; 88 for(int i=1,j=1;i<=cnt;i=j){ 89 p[++m]=p[i];mi[m]=0; 90 pk[m][0]=1; 91 for(;j<=cnt&&p[j]==p[i];j++){ 92 mi[m]++; 93 pk[m][mi[m]]=pk[m][mi[m]-1]*p[i]; 94 } 95 } 96 //for(int i=1;i<=m;i++)printf("%lld %lld\n",p[i],mi[i]); 97 ans=0; 98 dfs(1,1,1); 99 printf("%lld\n",ans); 100 } 101 return 0; 102 }
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define int long long 7 using namespace std; 8 int n,m,K,ans,mod,T; 9 int p[55],cnt,mi[55],pk[55][66]; 10 int R(int x){ 11 return rand()*rand()%x; 12 } 13 int mul(int a,int b,int p){ 14 return (a*b-(int)(((long double)a*b+0.5)/p)*p+p)%p; 15 } 16 int qp(int a,int b,int c){ 17 int ans=1; 18 for(;b;b>>=1,a=mul(a,a,c)) 19 if(b&1)ans=mul(ans,a,c); 20 return ans; 21 } 22 int prime[10]={0,2,3,5,7,11}; 23 bool miller_rabin(int x){ 24 if(x==1)return 0; 25 for(int i=1;i<=5;i++)if(x==prime[i])return 1; 26 for(int i=1;i<=5;i++)if(x%prime[i]==0)return 0; 27 int y=x-1,cnt=0; 28 while(!(y&1))y>>=1,cnt++; 29 for(int i=1;i<=5;i++){ 30 int now=qp(prime[i],y,x),nxt; 31 for(int j=1;j<=cnt;j++){ 32 nxt=mul(now,now,x); 33 if(nxt==1&&now!=1&&now!=x-1)return 0; 34 now=nxt; 35 } 36 if(nxt!=1)return 0; 37 } 38 return 1; 39 } 40 int gcd(int a,int b){return !b?a:gcd(b,a%b);} 41 int pollard_rho(int x,int y){ 42 int c=R(x-1)+1,d=c,g=1; 43 for(int i=1,j=2;g==1;i++){ 44 c=(mul(c,c,x)+y)%x; 45 g=gcd(abs(c-d),x); 46 if(i==j)d=c,j<<=1; 47 } 48 return g; 49 } 50 void divide(int x){ 51 if(x==1)return ; 52 if(miller_rabin(x)){ 53 p[++cnt]=x; 54 return ; 55 } 56 int now=x; 57 while(now==x)now=pollard_rho(x,R(x-1)); 58 divide(now); 59 divide(x/now); 60 } 61 void UPD(int &a,int b){ 62 a=(a+b>=mod)?(a+b-mod):(a+b); 63 } 64 void dfs(int x,int pos,int now){ 65 if(x==m+1){ 66 UPD(ans,(now%mod+mod)%mod*qp(K,(pos+1)/2,mod)%mod); 67 return ; 68 } 69 if(p[x]!=2) 70 for(int i=0;i<=mi[x];i++) 71 dfs(x+1,pos*pk[x][i],(i==mi[x])?now*pk[x][i]:now*(pk[x][i]*(1-p[x]))); 72 else 73 for(int i=0;i<mi[x];i++) 74 dfs(x+1,pos*pk[x][i+1],(i==mi[x]-1)?now*pk[x][i]:now*(pk[x][i]*(1-p[x]))); 75 } 76 signed main(){ 77 //freopen("test.in","r",stdin); 78 scanf("%lld",&T); 79 while(T--){ 80 scanf("%lld%lld%lld",&n,&K,&mod);K%=mod; 81 cnt=0; 82 divide(n); 83 sort(p+1,p+cnt+1); 84 m=0; 85 for(int i=1,j=1;i<=cnt;i=j){ 86 p[++m]=p[i];mi[m]=0; 87 pk[m][0]=1; 88 for(;j<=cnt&&p[j]==p[i];j++){ 89 mi[m]++; 90 pk[m][mi[m]]=pk[m][mi[m]-1]*p[i]; 91 } 92 } 93 ans=0; 94 dfs(1,1,1); 95 printf("%lld\n",ans); 96 } 97 return 0; 98 }
今天更爆炸,上來玩了題答的前三個點,而後看了眼狀態,wqA了T2,而後去搞,沒搞出來,而後lc又在旁邊大喊大叫說本身A了T1,以後寫了個20分,打了個表,其實都要找出來了沒仔細看,而後gg。T2puts("2")。0+25+58=83,T1冪處理的s的,T2暴力O(n^2)95?T3數組開小白扔10分?,什麼玩意啊。。。操。。。菜!
T1式子懶得寫了,就是一堆插板法合併起來。個人表都打出來了啊,就差一點,QAQ。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 1000500 7 using namespace std; 8 int n,m,s,invs,mx,mod,ans,fac[N<<2],inv[N<<2],pw[N<<2]; 9 void UPD(int &a,int b){ 10 a=(a+b>=mod)?(a+b-mod):(a+b); 11 } 12 int qp(int a,int b){ 13 int c=1; 14 for(;b;b>>=1,a=1ll*a*a%mod) 15 if(b&1)c=1ll*c*a%mod; 16 return c; 17 } 18 int C(int n,int m){ 19 if(m>n||m<0)return 0; 20 if(m==0||m==n)return 1; 21 return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod; 22 } 23 int main(){ 24 scanf("%d%d%d%d",&n,&m,&s,&mod); 25 mx=2*m+n+s; 26 fac[0]=1; 27 for(int i=1;i<=mx;i++)fac[i]=1ll*fac[i-1]*i%mod; 28 inv[mx]=qp(fac[mx],mod-2); 29 for(int i=mx;i;i--)inv[i-1]=1ll*inv[i]*i%mod; 30 invs=qp(s+1,mod-2); 31 pw[0]=qp(s+1,1ll*n*m%(mod-1)); 32 for(int i=1;i<=(n+m)<<1;i++)pw[i]=1ll*pw[i-1]*invs%mod; 33 for(int i=0;i<=m-2;i++) 34 UPD(ans,1ll*C(n-2+i,i)*C(n+m+s+i-3,s-n+1)%mod*pw[((i+n-1)<<1|1)+(m-i-1)]%mod); 35 for(int i=0;i<=n-2&&i<=s;i++) 36 UPD(ans,1ll*C(m-2+i,i)*C(2*m+n+s-4,s-i)%mod*pw[((i+m-1)<<1|1)+(n-i-1)]%mod); 37 printf("%d\n",ans); 38 return 0; 39 }
T2,最小鏈覆蓋等於最長反鏈,具體我也不是特別懂。而後就是個裸的cdq啦。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 200500 7 using namespace std; 8 struct data{int id,x1,x2,x3,x4;}d[N]; 9 bool cmpx1(data a,data b){return a.x1<b.x1;} 10 bool cmpx2(data a,data b){return a.x2<b.x2;} 11 int n,num[N],num_cnt,f[N],c[N],ans; 12 void add(int x,int y){for(;x<=num_cnt;x+=x&-x)c[x]=max(c[x],y);} 13 int query(int x){int y=0;for(;x;x-=x&-x)y=max(y,c[x]);return y;} 14 void clear(int x){for(;x<=num_cnt;x+=x&-x)c[x]=0;} 15 void cdq(int l,int r){ 16 if(l==r){ 17 f[d[l].id]=max(f[d[l].id],1); 18 return ; 19 } 20 int mid=(l+r)>>1; 21 cdq(l,mid); 22 sort(d+l,d+mid+1,cmpx2); 23 sort(d+mid+1,d+r+1,cmpx1); 24 for(int i=mid+1,j=l;i<=r;i++){ 25 for(;j<=mid&&d[j].x2<d[i].x1;j++) 26 add(d[j].x4,f[d[j].id]); 27 f[d[i].id]=max(f[d[i].id],query(d[i].x3)+1); 28 } 29 for(int i=l;i<=mid;i++)clear(d[i].x4); 30 cdq(mid+1,r); 31 } 32 int main(){ 33 scanf("%d",&n); 34 for(int i=1;i<=n;i++){ 35 d[i].id=i; 36 scanf("%d%d%d%d",&d[i].x1,&d[i].x2,&d[i].x3,&d[i].x4); 37 num[++num_cnt]=d[i].x3; 38 num[++num_cnt]=d[i].x4; 39 } 40 sort(num+1,num+num_cnt+1); 41 for(int i=1;i<=n;i++) 42 d[i].x3=lower_bound(num+1,num+num_cnt+1,d[i].x3)-num, 43 d[i].x4=lower_bound(num+1,num+num_cnt+1,d[i].x4)-num; 44 sort(d+1,d+n+1,cmpx1); 45 cdq(1,n); 46 for(int i=1;i<=n;i++)ans=max(ans,f[i]); 47 printf("%d\n",ans); 48 return 0; 49 }
T3最小生成樹有68分,正解好像是發現點構成了一些直線,而後巴拉巴拉什麼的。
加油加油!!!!!!!
5.24IOI賽制
考試先看T1,不太會,而後想了一會,發現就是三維偏序,log2穩T,寫了個cdq和暴力拍,沒事就交了,60分,而後看後兩題都只會暴力的樣子,而後先寫了T2的25分暴力,而後想40分,要處理全部迴文串的出現次數?不行啊。而後看T3,嘗試着puts2,10分,加了個puts0,40,又寫了個快速冪,60。
T1,把三個兩兩組合作二維偏序,答案就是全部的減去這三個答案再除以2。證實的話,110+111+101+111+011+111=3*111+(110+101+011)=C(n,2)+2*111;
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define LL long long 7 #define N 2000500 8 using namespace std; 9 int n,c[N]; 10 void add(int x){for(;x<=n;x+=x&-x)c[x]++;} 11 int query(int x){int ans=0;for(;x;x-=x&-x)ans+=c[x];return ans;} 12 LL ans; 13 struct data{int a,b,c;}d[N],tmp[N]; 14 bool cmpa(data a,data b){return a.a<b.a;} 15 bool cmpb(data a,data b){return a.b<b.b;} 16 LL seed; 17 LL Rand(){return seed=((seed*19260817)^233333)&((1<<24)-1);} 18 LL work1(){ 19 LL ans=0; 20 memset(c,0,sizeof c); 21 sort(d+1,d+n+1,cmpa); 22 for(int i=1;i<=n;i++){ 23 ans+=query(d[i].b); 24 add(d[i].b); 25 } 26 return ans; 27 } 28 LL work2(){ 29 LL ans=0; 30 memset(c,0,sizeof c); 31 sort(d+1,d+n+1,cmpa); 32 for(int i=1;i<=n;i++){ 33 ans+=query(d[i].c); 34 add(d[i].c); 35 } 36 return ans; 37 } 38 LL work3(){ 39 LL ans=0; 40 memset(c,0,sizeof c); 41 sort(d+1,d+n+1,cmpb); 42 for(int i=1;i<=n;i++){ 43 ans+=query(d[i].c); 44 add(d[i].c); 45 } 46 return ans; 47 } 48 int main(){ 49 scanf("%d",&n); 50 for(int i=1;i<=n;i++)d[i].a=d[i].b=d[i].c=i; 51 scanf("%lld",&seed);for(int i=1;i<=n;i++)swap(d[i].a,d[Rand()%i+1].a); 52 scanf("%lld",&seed);for(int i=1;i<=n;i++)swap(d[i].b,d[Rand()%i+1].b); 53 scanf("%lld",&seed);for(int i=1;i<=n;i++)swap(d[i].c,d[Rand()%i+1].c); 54 ans=work1()+work2()+work3()-1ll*n*(n-1)/2; 55 printf("%lld\n",ans/2); 56 return 0; 57 }
T2,迴文自動機+樹剖,複習了迴文自動機,不錯。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define int long long 7 #define N 200005 8 using namespace std; 9 struct data{ 10 char o[10]; 11 int x,l1,r1,l2,r2; 12 }d[N]; 13 int n,m,a[N],s[N],L,nowl,nowr,pp1[N],pp2[N]; 14 int e=1,head[N]; 15 struct edge{ 16 int v,next; 17 }ed[N]; 18 void add(int u,int v){ 19 ed[e].v=v; 20 ed[e].next=head[u]; 21 head[u]=e++; 22 } 23 int ch[N][26],fail[N],len[N],tot; 24 int getfail(int x,int p){ 25 while(s[p]!=s[p-len[x]-1])x=fail[x]; 26 return x; 27 } 28 int getfail1(int x,int p){ 29 while(s[p]!=s[p+len[x]+1])x=fail[x]; 30 return x; 31 } 32 void extend(int pos,int c){ 33 int p=getfail(pp1[pos-1],pos); 34 if(!ch[p][c]){ 35 int np=++tot; 36 len[np]=len[p]+2; 37 int q=getfail(fail[p],pos); 38 fail[np]=ch[q][c]; 39 ch[p][c]=np; 40 add(fail[np],np); 41 } 42 pp1[pos]=ch[p][c]; 43 } 44 void travel(int x,int pos){ 45 pp2[x]=pos; 46 if(x==1)return ; 47 int p=getfail1(pos,x-1); 48 travel(x-1,ch[p][s[x-1]]); 49 } 50 int dep[N],size[N],son[N],top[N],id[N],pp[N],num,fa[N][20],LCA; 51 int sum[N<<2],sum_val[N<<2],lazy[N<<2]; 52 void dfs1(int x,int d){ 53 dep[x]=d;size[x]=1; 54 son[x]=tot+1; 55 for(int i=1;(1<<i)<=dep[x];i++) 56 fa[x][i]=fa[fa[x][i-1]][i-1]; 57 for(int i=head[x];i;i=ed[i].next){ 58 int v=ed[i].v; 59 fa[v][0]=x;dfs1(v,d+1); 60 size[x]+=size[v]; 61 if(size[v]>size[son[x]])son[x]=v; 62 } 63 } 64 void dfs2(int x,int t){ 65 id[x]=++num,pp[num]=x,top[x]=t; 66 if(son[x]!=tot+1)dfs2(son[x],t); 67 for(int i=head[x];i;i=ed[i].next){ 68 int v=ed[i].v; 69 if(v==son[x])continue; 70 dfs2(v,v); 71 } 72 } 73 void build(int rt,int l,int r){ 74 if(l==r){ 75 sum[rt]=len[pp[l]]>0?len[pp[l]]:0; 76 return ; 77 } 78 int mid=(l+r)>>1; 79 build(rt<<1,l,mid); 80 build(rt<<1|1,mid+1,r); 81 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 82 } 83 void update_lazy(int rt,int x){ 84 lazy[rt]+=x; 85 sum_val[rt]+=x*sum[rt]; 86 } 87 void pushdown(int rt){ 88 if(lazy[rt]){ 89 update_lazy(rt<<1,lazy[rt]); 90 update_lazy(rt<<1|1,lazy[rt]); 91 lazy[rt]=0; 92 } 93 } 94 void pushup(int rt){ 95 sum_val[rt]=sum_val[rt<<1]+sum_val[rt<<1|1]; 96 } 97 void update(int rt,int l,int r,int x,int y){ 98 if(x<=l&&r<=y){ 99 update_lazy(rt,1); 100 return ; 101 } 102 pushdown(rt); 103 int mid=(l+r)>>1; 104 if(x<=mid)update(rt<<1,l,mid,x,y); 105 if(y>mid)update(rt<<1|1,mid+1,r,x,y); 106 pushup(rt); 107 } 108 int query(int rt,int l,int r,int x,int y){ 109 if(x<=l&&r<=y)return sum_val[rt]; 110 int mid=(l+r)>>1; 111 pushdown(rt); 112 if(y<=mid)return query(rt<<1,l,mid,x,y); 113 if(x>mid)return query(rt<<1|1,mid+1,r,x,y); 114 return query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y); 115 } 116 void update(int x){ 117 do{ 118 update(1,1,tot+1,id[top[x]],id[x]); 119 x=fa[top[x]][0]; 120 }while(x<=tot); 121 } 122 void extendr(int pos){ 123 int x=pp1[pos]; 124 for(int i=18;~i;i--) 125 if(pos-len[fa[x][i]]+1<nowl)x=fa[x][i]; 126 if(pos-len[x]+1<nowl)x=fa[x][0]; 127 update(x); 128 } 129 void extendl(int pos){ 130 int x=pp2[pos]; 131 for(int i=18;~i;i--) 132 if(pos+len[fa[x][i]]-1>nowr)x=fa[x][i]; 133 if(pos+len[x]-1>nowr)x=fa[x][0]; 134 update(x); 135 } 136 int query(int x,int y){ 137 int ans=0; 138 while(top[x]!=top[y]){ 139 if(dep[top[x]]<dep[top[y]])swap(x,y); 140 ans+=query(1,1,tot+1,id[top[x]],id[x]); 141 x=fa[top[x]][0]; 142 } 143 if(dep[x]>dep[y])swap(x,y); 144 ans+=query(1,1,tot+1,id[x],id[y]); 145 LCA=x; 146 return ans; 147 } 148 void queryr(int l1,int r1,int l2,int r2){ 149 int x=pp2[l1],y=pp2[l2]; 150 for(int i=18;~i;i--) 151 if(l1+len[fa[x][i]]-1>r1)x=fa[x][i]; 152 if(l1+len[x]-1>r1)x=fa[x][0]; 153 for(int i=18;~i;i--) 154 if(l2+len[fa[y][i]]-1>r2)y=fa[y][i]; 155 if(l2+len[y]-1>r2)y=fa[y][0]; 156 int ans=query(x,y); 157 if((len[LCA]<(r1-l1+1)&&len[LCA]<(r2-l2+1))&&s[l1+len[LCA]]==s[l2+len[LCA]]) 158 ans-=query(1,1,tot+1,id[LCA],id[LCA]); 159 printf("%lld\n",ans); 160 } 161 void queryl(int l1,int r1,int l2,int r2){ 162 int x=pp1[r1],y=pp1[r2]; 163 for(int i=18;~i;i--) 164 if(r1-len[fa[x][i]]+1<l1)x=fa[x][i]; 165 if(r1-len[x]+1<l1)x=fa[x][0]; 166 for(int i=18;~i;i--) 167 if(r2-len[fa[y][i]]+1<l2)y=fa[y][i]; 168 if(r2-len[y]+1<l2)y=fa[y][0]; 169 int ans=query(x,y); 170 if((len[LCA]<(r1-l1+1)&&len[LCA]<(r2-l2+1))&&s[r1-len[LCA]]==s[r2-len[LCA]]) 171 ans-=query(1,1,tot+1,id[LCA],id[LCA]); 172 printf("%lld\n",ans); 173 } 174 signed main(){ 175 scanf("%lld%lld",&n,&m); 176 for(int i=1;i<=n;i++) 177 scanf("%lld",&a[i]); 178 for(int i=1;i<=m;i++){ 179 scanf("%s",d[i].o); 180 if(d[i].o[0]=='a') 181 scanf("%lld",&d[i].x); 182 else scanf("%lld%lld%lld%lld",&d[i].l1,&d[i].r1,&d[i].l2,&d[i].r2); 183 } 184 s[0]=-1; 185 for(int i=m;i;i--) 186 if(d[i].o[0]=='a'&&d[i].o[3]=='l') 187 s[++L]=d[i].x; 188 nowl=L+1; 189 for(int i=1;i<=n;i++)s[++L]=a[i]; 190 nowr=L; 191 for(int i=1;i<=m;i++) 192 if(d[i].o[0]=='a'&&d[i].o[3]=='r') 193 s[++L]=d[i].x; 194 s[L+1]=-1; 195 tot=1;len[1]=-1; 196 fail[0]=fail[1]=1; 197 add(1,0); 198 for(int i=1;i<=L;i++) 199 extend(i,s[i]); 200 travel(L+1,0); 201 fa[1][0]=tot+1; 202 dfs1(1,1); 203 dfs2(1,1); 204 build(1,1,tot+1); 205 for(int i=nowl;i<=nowr;i++)extendr(i); 206 for(int i=1;i<=m;i++){ 207 if(d[i].o[0]=='t'){ 208 if(d[i].o[5]=='l')queryl(nowl-1+d[i].l1,nowl-1+d[i].r1,nowl-1+d[i].l2,nowl-1+d[i].r2); 209 else queryr(nowl-1+d[i].l1,nowl-1+d[i].r1,nowl-1+d[i].l2,nowl-1+d[i].r2); 210 } 211 else{ 212 if(d[i].o[3]=='l')extendl(--nowl); 213 else extendr(++nowr); 214 } 215 } 216 return 0; 217 }
5.25
先看T1,推了推,只會60暴搜,而後看T2,不太清楚,看T3,好像會20騙分。寫T1,寫完60分總感受能夠直接dp,可是怎麼想也想不出來。而後又亂搞了一會,也沒想出來啥別的作法,後來只剩90min了,趕忙去寫T2,O(n)的式子推了我很久,花了一個多小時寫完了,而後測了組極限數據,6s??後來發現是由於我在結構體裏開了個vector,而後sort就炸了。最後沒改完,只得了20分,T3暴力都沒交。
原本感受這場考試應該能考得不錯的,而後就是炸,不行啊!
T1就是個簡單的小dp,爲何我就想不到?包括ctscD1T1,我想了1h+,多是這陣作的dp太少了吧,必需要思考,尤爲是這種沒思路的,想一想最基本的狀態定義還有轉移,也許真的不難。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define mod 1000000007 7 #define N 100500 8 using namespace std; 9 int qp(int a,int b){ 10 int c=1; 11 for(;b;b>>=1,a=1ll*a*a%mod) 12 if(b&1)c=1ll*c*a%mod; 13 return c; 14 } 15 int fac[N],inv[N]; 16 int num[10],now[10],nw[10],wcnt,Ans,n,len; 17 char s[N]; 18 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 19 int C(int n,int m){ 20 if(m==n||m==0)return 1; 21 return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod; 22 } 23 int f[2][1050]; 24 void work(){ 25 for(int i=1;i<=5;i++){ 26 for(int j=0;j<=9;j++)now[j]=num[j]; 27 now[i]--;now[10-i]--; 28 int ii=0;memset(f[ii],0,sizeof f[ii]); 29 for(int j=max(0,0-now[9]);j<=wcnt;j++) 30 for(int k=max(0,now[9]+j-now[0]);j+k<=wcnt;k++) 31 UPD(f[ii][j+k],1ll*C(wcnt,j)*C(wcnt-j,k)%mod); 32 for(int j=1;j<=4;j++){ 33 ii^=1;memset(f[ii],0,sizeof f[ii]); 34 for(int k1=max(0,max(0,now[9-j])-now[j]),k2=now[j]+k1-now[9-j];k1+k2<=wcnt;k1++,k2++){ 35 for(int l=0;l+k1+k2<=wcnt;l++) 36 UPD(f[ii][l+k1+k2],1ll*f[ii^1][l]*C(wcnt-l,k1)%mod*C(wcnt-l-k1,k2)%mod); 37 } 38 } 39 UPD(Ans,f[ii][wcnt]); 40 } 41 } 42 int main(){ 43 scanf("%s",s+1); 44 len=strlen(s+1);n=len>>1; 45 for(int i=1;i<=len;i++){ 46 if(s[i]=='?')wcnt++; 47 else num[s[i]-'0']++; 48 } 49 fac[0]=1; 50 for(int i=1;i<=wcnt;i++)fac[i]=1ll*fac[i-1]*i%mod; 51 inv[wcnt]=qp(fac[wcnt],mod-2); 52 for(int i=wcnt;i>=1;i--)inv[i-1]=1ll*inv[i]*i%mod; 53 work(); 54 printf("%d\n",Ans); 55 return 0; 56 }
T2,我犯了好幾個小錯誤,在這說一下吧,首先是在結構體裏開vector,雖然只有一個數,可是常數一下打了若干倍,其次就是在函數中定義變量沒有初始化,再有就是inf開的不夠大,反正全是小毛病,細心,再細心。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #include <vector> 8 #define N 100500 9 #define eps 1e-12 10 #define inf 0x7fffffffffffffff 11 #define pb push_back 12 using namespace std; 13 int n; 14 double w[N],sw[N],d[N],sd[N],SUM[N],DIS[N],Ans[N],l[N],r[N],down,up; 15 int tot,top,be,pp[N]; 16 vector <int> V[N]; 17 struct point{ 18 double x,y; 19 int id; 20 point(){x=y=0;} 21 point(double a,double b){x=a;y=b;} 22 point operator - (point a){return point(x-a.x,y-a.y);} 23 double operator * (point a){return x*a.y-y*a.x;} 24 }p[N],q[N]; 25 double getdis(point a){ 26 return sqrt(a.x*a.x+a.y*a.y); 27 } 28 bool cmp(point a,point b){ 29 double now=(a-p[1])*(b-p[1]); 30 if(now==0)return getdis(a-p[1])<getdis(b-p[1]); 31 return now>0; 32 } 33 int getf(double a){ 34 if(a<-eps)return -1; 35 if(a>eps)return 1; 36 return 0; 37 } 38 int vis[N],cnt; 39 namespace work1{ 40 void Main(){ 41 sw[n]=sw[n-1]+down; 42 double x1=0,x2=0,sum1=0,sum2=0; 43 x1=d[1];sum1=w[n]*x1; 44 SUM[1]=d[n]*sum1; 45 for(int i=n-1;i>=2;i--){ 46 x1+=d[i+1]; 47 sum1+=w[i]*x1; 48 SUM[1]+=d[i]*sum1; 49 } 50 for(int i=3;i<=n;i++){ 51 x2+=d[i]; 52 sum2+=x2*w[i]; 53 } 54 x2+=d[1];sum2+=x2*w[1]; 55 for(int i=2;i<=n;i++){ 56 SUM[i]=SUM[i-1]-d[i]*sum1+d[i]*sum2; 57 sum1+=d[i]*sw[n];sum1-=sd[n]*w[i]; 58 sum2+=sd[n]*w[i];sum2-=d[i+1]*sw[n]; 59 } 60 double ans=SUM[1]; 61 for(int i=2;i<=n;i++) 62 ans=min(ans,SUM[i]); 63 for(int i=1;i<=n;i++) 64 if(getf(ans-SUM[i])==0)cnt++,vis[i]=1; 65 for(int i=1;i<=n;i++){ 66 if(vis[i])printf("%0.3f\n",1.0/1.0/(1.0*cnt)); 67 else puts("0.000"); 68 } 69 } 70 } 71 int main(){ 72 scanf("%d%lf%lf",&n,&down,&up); 73 for(int i=1;i<n;i++){ 74 scanf("%lf",&w[i]); 75 sw[i]=sw[i-1]+w[i]; 76 } 77 sw[n]=sw[n-1]; 78 for(int i=1;i<=n;i++){ 79 scanf("%lf",&d[i]); 80 sd[i]=sd[i-1]+d[i]; 81 } 82 if(down==up){ 83 work1::Main(); 84 return 0; 85 } 86 for(int i=1;i<n;i++) 87 DIS[i]=(sd[n]-sd[i])*(sd[i]); 88 double x1=0,x2=0,sum1=0,sum2=0; 89 x1=d[1];sum1=w[n]*x1; 90 SUM[1]=d[n]*sum1; 91 for(int i=n-1;i>=2;i--){ 92 x1+=d[i+1]; 93 sum1+=w[i]*x1; 94 SUM[1]+=d[i]*sum1; 95 } 96 for(int i=3;i<=n;i++){ 97 x2+=d[i]; 98 sum2+=x2*w[i]; 99 } 100 x2+=d[1];sum2+=x2*w[1]; 101 for(int i=2;i<=n;i++){ 102 SUM[i]=SUM[i-1]-d[i]*sum1+d[i]*sum2; 103 sum1+=d[i]*sw[n];sum1-=sd[n]*w[i]; 104 sum2+=sd[n]*w[i];sum2-=d[i+1]*sw[n]; 105 } 106 for(int i=1;i<=n;i++){ 107 p[i]=point(DIS[i],SUM[i]); 108 p[i].id=i; 109 } 110 swap(p[1],p[n]); 111 sort(p+2,p+n+1,cmp); 112 tot=0; 113 for(int i=1,j=1;i<=n;i=j){ 114 p[++tot]=p[i]; 115 for(;j<=n&&getf(p[i].x-p[j].x)==0&&getf(p[i].y-p[j].y)==0;j++) 116 V[tot].pb(p[j].id); 117 } 118 q[1]=p[1];top=1;pp[1]=1; 119 for(int i=2;i<=tot;i++){ 120 while(top>1&&(p[i]-q[top])*(q[top]-q[top-1])>=0)top--; 121 q[++top]=p[i]; 122 pp[top]=i; 123 } 124 tot=top; 125 for(int i=1;i<=tot;i++)p[i]=q[i]; 126 while(tot>1&&(p[tot].y>p[tot-1].y||p[tot].x<p[tot-1].x))tot--; 127 l[1]=inf; 128 for(int i=1;i<tot;i++){ 129 r[i]=(p[i].y-p[i+1].y)/(p[i+1].x-p[i].x); 130 l[i+1]=r[i]; 131 } 132 r[tot]=0; 133 for(int i=1;i<=tot;i++) 134 if(r[i]<up){be=i;break;} 135 for(int i=be;i<=tot;i++){ 136 if(l[i]<down)break; 137 double now=(min(up,l[i])-max(down,r[i]))/(up-down)/(1.0*V[pp[i]].size()); 138 for(int j=0;j<V[pp[i]].size();j++){ 139 Ans[V[pp[i]][j]]=now; 140 } 141 } 142 for(int i=1;i<=n;i++)printf("%0.3f\n",Ans[i]); 143 return 0; 144 }
T3,挺好的一個腦洞題,不想寫了,怎麼我愈來愈懶了呢?
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #include <vector> 8 #define N 13333 9 #define LL long long 10 #define pb push_back 11 using namespace std; 12 int n,m,top,tot,e,pos; 13 struct data{ 14 int u,v; 15 data(){} 16 data(int a,int b){u=a;v=b;} 17 }d[N]; 18 bool cmpd(const data & a,const data & b){return a.u<b.u;} 19 struct point{ 20 int x,y,id,be; 21 point(){x=y=0;} 22 point(int a,int b){x=a;y=b;} 23 point operator - (const point & a)const{return point(x-a.x,y-a.y);} 24 LL operator * (const point & a)const{return 1ll*x*a.y-1ll*y*a.x;} 25 }p[N],q[N]; 26 LL getdis(const point & a){ 27 return sqrt(1ll*a.x*a.x+1ll*a.y*a.y); 28 } 29 bool cmp(const point & a,const point & b){ 30 LL now=(a-p[1])*(b-p[1]); 31 if(now==0)return getdis(a-p[1])<getdis(b-p[1]); 32 return now>0; 33 } 34 bool check(const point & a,const point & b,const point & c,const point & p){ 35 LL x1=(b-a)*(p-a),x2=(c-b)*(p-b),x3=(a-c)*(p-c); 36 if(x1==0||x2==0||x3==0)return 0; 37 if(x1>0){if(x2<0||x3<0)return 0;return 1;} 38 if(x1<0){if(x2>0||x3>0)return 0;return 1;} 39 } 40 void graham(){ 41 tot=n+m; 42 for(int i=2;i<=tot;i++)if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[1].y)) 43 swap(p[1],p[i]); 44 sort(p+2,p+tot+1,cmp); 45 q[1]=p[1];top=1; 46 for(int i=2;i<=tot;i++){ 47 while(top>1&&(p[i]-q[top])*(q[top]-q[top-1])>0)top--; 48 q[++top]=p[i]; 49 } 50 int posl=2,posr=top-1; 51 for(;posl<=top&&q[posl].be==q[posl-1].be;posl++);posl--; 52 for(;posr>=1&&q[posr].be==q[posr+1].be;posr--);posr++; 53 if(posl+1<posr){ 54 int c=q[posl+1].be; 55 for(int i=posl+1;i<posr;i++) 56 if(q[i].be!=c){puts("GG!");exit(0);} 57 for(int i=1;i<=posl;i++)q[top+i]=q[i]; 58 for(int i=1;i<=top;i++)q[i]=q[i+posl]; 59 pos=posr-posl; 60 } 61 else if(posl+1==posr){ 62 pos=posr; 63 } 64 } 65 int num; 66 vector<int> V[N]; 67 void work(const point & a,const point & b,const point & c,int now){ 68 int cnt1=0,cnt2=0; 69 for(int i=0;i<V[now].size();i++){ 70 if(p[V[now][i]].be==a.be)cnt1++; 71 else cnt2++; 72 } 73 if(!cnt1&&!cnt2)return ; 74 if(!cnt1){ 75 for(int i=0;i<V[now].size();i++) 76 if(check(a,b,c,p[V[now][i]])&&p[V[now][i]].be==b.be)d[++e]=data(b.id,p[V[now][i]].id); 77 return ; 78 } 79 if(!cnt2){ 80 for(int i=0;i<V[now].size();i++) 81 if(check(a,b,c,p[V[now][i]])&&p[V[now][i]].be==a.be)d[++e]=data(a.id,p[V[now][i]].id); 82 return ; 83 } 84 for(int i=0;i<V[now].size();i++) 85 if(check(a,b,c,p[V[now][i]])&&p[V[now][i]].be==a.be){ 86 d[++e]=data(a.id,p[V[now][i]].id); 87 int nxt=++num; 88 for(int j=0;j<V[now].size();j++) 89 if(check(b,a,p[V[now][i]],p[V[now][j]])) 90 V[nxt].pb(V[now][j]); 91 work(b,a,p[V[now][i]],nxt); 92 nxt=++num; 93 for(int j=0;j<V[now].size();j++) 94 if(check(c,a,p[V[now][i]],p[V[now][j]])) 95 V[nxt].pb(V[now][j]); 96 work(c,a,p[V[now][i]],nxt); 97 nxt=++num; 98 for(int j=0;j<V[now].size();j++) 99 if(check(p[V[now][i]],b,c,p[V[now][j]])) 100 V[nxt].pb(V[now][j]); 101 work(p[V[now][i]],b,c,nxt); 102 return ; 103 } 104 } 105 int main(){ 106 scanf("%d%d",&n,&m); 107 if(!n||!m){ 108 for(int i=1;i<max(n,m);i++)printf("%d %d\n",i,m); 109 return 0; 110 } 111 for(int i=1;i<=n;i++){ 112 scanf("%d%d",&p[i].x,&p[i].y); 113 p[i].id=i;p[i].be=1; 114 } 115 for(int i=1;i<=m;i++){ 116 scanf("%d%d",&p[n+i].x,&p[n+i].y); 117 p[n+i].id=n+i;p[n+i].be=2; 118 } 119 graham(); 120 if(q[top].be==q[1].be){ 121 for(int i=1;i<=n;i++){ 122 if(p[i].be!=q[1].be){ 123 for(int j=1;j<top;j++){ 124 d[++e]=data(q[j].id,q[j+1].id); 125 int now=++num; 126 for(int k=1;k<=tot;k++) 127 if(check(p[i],q[j],q[j+1],p[k]))V[now].pb(k); 128 work(p[i],q[j],q[j+1],now); 129 } 130 int now=++num; 131 for(int k=1;k<=tot;k++) 132 if(check(p[i],q[1],q[top],p[k]))V[now].pb(k); 133 work(p[i],q[1],q[top],now); 134 break; 135 } 136 } 137 sort(d+1,d+e+1,cmpd); 138 for(int i=1;i<n;i++)printf("%d %d\n",d[i].u,d[i].v); 139 for(int i=n;i<n+m-1;i++)printf("%d %d\n",d[i].u-n,d[i].v-n); 140 return 0; 141 } 142 for(int i=1;i<pos-1;i++){ 143 d[++e]=data(q[i].id,q[i+1].id); 144 int now=++num; 145 for(int j=1;j<=tot;j++) 146 if(check(q[pos],q[i],q[i+1],p[j]))V[now].pb(j); 147 work(q[pos],q[i],q[i+1],now); 148 } 149 for(int i=pos;i<top;i++){ 150 d[++e]=data(q[i].id,q[i+1].id); 151 int now=++num; 152 for(int j=1;j<=tot;j++) 153 if(check(q[1],q[i],q[i+1],p[j]))V[now].pb(j); 154 work(q[1],q[i],q[i+1],now); 155 } 156 sort(d+1,d+e+1,cmpd); 157 for(int i=1;i<n;i++)printf("%d %d\n",d[i].u,d[i].v); 158 for(int i=n;i<n+m-1;i++)printf("%d %d\n",d[i].u-n,d[i].v-n); 159 }
加油啊!!!!
5.26
先看T1,要O(nqlog),有60分?而後看T2,一點不會,而後看T3,想了一個ac自動機的玄學作法,寫出來小樣例都過了,本身造的極限數據跑的很快,而後去想T1,發現很水,寫了個線段樹,而後拍上了。最後去寫了T2的暴力,感受能上200?80+60+25=165 rank6,T1被卡常了,根本不用線段樹,直接開個變量就能夠,T2的暴力卻是多拿了很多分,T3徹底看錯題了,居然有分,挺好。
此次也暴露出了個人很多問題,T1線段樹徹底是多餘的,可是我想到以後沒有深刻去思考本質,因而就gg了。而後又是T3的讀題問題,原來是有一段時間想錯誤的題意,此次是徹底看錯題意,之後讀題要細心再細心。
T1,咱們發現只需處理相鄰元素就好,而後每對相鄰元素可能須要動的就是最高的不相同位,而後記錄一下每一位就行了。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #define N 1000500 8 #define B 35 9 using namespace std; 10 int n,m,a[N],s[N],hi[N],num1[B],num2[B],bit[B],Ans; 11 12 int read(){ 13 int a=0;char ch=getchar(); 14 while(ch<'0'||ch>'9')ch=getchar(); 15 while(ch>='0'&&ch<='9'){a=a*10+(ch^48);ch=getchar();} 16 return a; 17 } 18 void work(){ 19 Ans=0; 20 for(int i=29;~i;i--){ 21 if(num1[i]&&num2[i]){puts("-1");return;} 22 if(num1[i])Ans|=bit[i]; 23 } 24 printf("%d\n",Ans); 25 } 26 int main(){ 27 bit[0]=1; 28 for(int i=1;i<=29;i++)bit[i]=bit[i-1]<<1; 29 n=read(); 30 for(int i=1;i<=n;i++)a[i]=read(); 31 memset(hi,-1,sizeof hi); 32 for(int i=1;i<n;i++){ 33 s[i]=a[i]^a[i+1]; 34 for(int j=29;~j;j--) 35 if(s[i]&bit[j]){hi[i]=j;break;} 36 if(hi[i]!=-1){ 37 if(a[i]&bit[hi[i]])num1[hi[i]]++; 38 else num2[hi[i]]++; 39 } 40 } 41 work(); 42 m=read(); 43 for(int i=1,x,y;i<=m;i++){ 44 x=read();y=read(); 45 if(x>1){ 46 if(hi[x-1]!=-1){ 47 if(a[x-1]&(bit[hi[x-1]]))num1[hi[x-1]]--; 48 else num2[hi[x-1]]--; 49 } 50 s[x-1]=a[x-1]^y; 51 hi[x-1]=-1; 52 for(int j=29;~j;j--) 53 if(s[x-1]&bit[j]){hi[x-1]=j;break;} 54 if(hi[x-1]!=-1){ 55 if(a[x-1]&bit[hi[x-1]])num1[hi[x-1]]++; 56 else num2[hi[x-1]]++; 57 } 58 } 59 if(x<n){ 60 if(hi[x]!=-1){ 61 if(a[x]&(bit[hi[x]]))num1[hi[x]]--; 62 else num2[hi[x]]--; 63 } 64 s[x]=y^a[x+1]; 65 hi[x]=-1; 66 for(int j=29;~j;j--) 67 if(s[x]&bit[j]){hi[x]=j;break;} 68 if(hi[x]!=-1){ 69 if(y&(bit[hi[x]]))num1[hi[x]]++; 70 else num2[hi[x]]++; 71 } 72 } 73 a[x]=y; 74 work(); 75 } 76 return 0; 77 }
T2,咱們先把最短路跑出來,而後只保留有用的邊,而後對於一段連續的路線來講,能夠用斜率優化,而後隨便搞搞就好了。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 #include <map> 10 #define inf 0x7fffffff 11 #define N 1000500 12 #define LL long long 13 #define pb push_back 14 using namespace std; 15 int n,m,v[N],t[N],s[N]; 16 int dis[N],vis[N]; 17 int e=1,head[N]; 18 LL f[N]; 19 struct edge{ 20 int u,v,w,id,next; 21 }ed[N]; 22 void add(int u,int v,int w,int id){ 23 ed[e].u=u;ed[e].v=v;ed[e].w=w;ed[e].id=id; 24 ed[e].next=head[u];head[u]=e++; 25 } 26 queue<int> q; 27 void spfa(){ 28 memset(dis,0x3f,sizeof dis); 29 memset(vis,0,sizeof vis); 30 q.push(1); 31 dis[1]=0;vis[1]=1; 32 while(!q.empty()){ 33 int x=q.front();q.pop();vis[x]=0; 34 for(int i=head[x];i;i=ed[i].next){ 35 int v=ed[i].v; 36 if(dis[x]+ed[i].w<dis[v]){ 37 dis[v]=dis[x]+ed[i].w; 38 if(!vis[v]){vis[v]=1;q.push(v);} 39 } 40 } 41 } 42 } 43 LL getf(int u,int v){return -2ll*dis[u]*dis[v]+1ll*dis[u]*dis[u]+f[u];} 44 double getcross(int x,int y){return (double)(1ll*dis[x]*dis[x]+f[x]-1ll*dis[y]*dis[y]-f[y])/1.0/(2ll*dis[x]-2ll*dis[y]);} 45 int in[N],tot; 46 vector <int> qu[N]; 47 map <int,int> pp[N]; 48 int main(){ 49 scanf("%d%d",&n,&m); 50 for(int i=1,x,y,cnt,las;i<=m;i++){ 51 scanf("%d",&cnt); 52 scanf("%d",&las); 53 for(int j=1;j<=cnt;j++){ 54 scanf("%d%d",&y,&x); 55 add(las,x,y,i);las=x; 56 } 57 } 58 spfa(); 59 int le=e; 60 e=1;memset(head,0,sizeof head); 61 for(int i=1;i<le;i++) 62 if(dis[ed[i].u]+ed[i].w==dis[ed[i].v]){ 63 add(ed[i].u,ed[i].v,ed[i].w,ed[i].id); 64 in[ed[i].v]++; 65 } 66 memset(f,-0x3f,sizeof f); 67 f[1]=0;q.push(1); 68 while(!q.empty()){ 69 int x=q.front();q.pop(); 70 for(int i=head[x];i;i=ed[i].next){ 71 int v=ed[i].v,p=ed[i].id; 72 if(!pp[x].count(p))pp[x][p]=++tot; 73 int now=pp[x][p]; 74 pp[v][p]=now; 75 while(qu[now].size()>1&&getcross(qu[now][qu[now].size()-2],qu[now][qu[now].size()-1])<getcross(x,qu[now][qu[now].size()-2])) 76 qu[now].pop_back(); 77 qu[now].pb(x); 78 while(qu[now].size()>1&&getf(qu[now][qu[now].size()-2],v)>getf(qu[now][qu[now].size()-1],v)) 79 qu[now].pop_back(); 80 f[v]=max(f[v],1ll*dis[v]*dis[v]+getf(qu[now][qu[now].size()-1],v)); 81 in[v]--; 82 if(!in[v])q.push(v); 83 } 84 } 85 printf("%d %lld\n",dis[n],f[n]); 86 return 0; 87 }
T3,這題調了我很久啊,按根號分類討論,小的咱們暴力在trie樹上走,大的咱們線段樹優化轉移,這裏必定要注意先後綴的區別。
1 #pragma GCC optimize ("O3") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #include <queue> 8 #define LL long long 9 #define ull unsigned int 10 #define N 300500 11 #define P 333331 12 using namespace std; 13 int ch1[N][2],dep1[N],w1[N],tot1,root1; 14 int ch2[N][2],dep2[N],w2[N],tot2,root2; 15 int len,n,m,nn,w[155],ln[155],tot; 16 char s[N],c[N]; 17 LL f[N]; 18 ull pw[N],h[155][N]; 19 ull geth(int x,int l,int r){return h[x][r]-h[x][l-1]*pw[r-l+1];} 20 void add(int v,char *c){ 21 int l=strlen(c); 22 int now=root1; 23 for(int i=0;i<l;i++){ 24 int t=c[i]-'0'; 25 if(!ch1[now][t]){ 26 ch1[now][t]=++tot1; 27 dep1[tot1]=dep1[now]+1; 28 } 29 now=ch1[now][t]; 30 w1[now]=min(w1[now],v); 31 } 32 now=root2; 33 for(int i=l-1;~i;i--){ 34 int t=c[i]-'0'; 35 if(!ch2[now][t]){ 36 ch2[now][t]=++tot2; 37 dep2[tot2]=dep2[now]+1; 38