NOI前的考試日誌

 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 }
View Code

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 }
View Code

裸的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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

 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 }
View Code

 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 }
View Code

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 }
View Code

 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 }
View Code

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 }
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

正解網絡流,其實仍是套路,咱們把每一個點拆點,而後本身流一條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 }
View Code

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 }
View Code

翻翻翻!

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

正解更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 }
View Code

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 }
View Code

晚上回家打了場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 }
View Code

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 }
View Code

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 }
View Code

我愛拜仁。

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 }
View Code

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 }
View Code

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 }
View Code

虛...

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 }
View Code

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 }
View Code

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 }
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

加油加油,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 }
View Code

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 }
View Code

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 }
View Code

加油!!!

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 }
View Code

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 }
View Code

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 }
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

水平不行啊。

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 }
View Code

保持思考。

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

加油啊!!!!

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 }
View Code

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 }
View Code

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 
相關文章
相關標籤/搜索