2015 Multi-University Training Contest 8

1001 Travel with candy

 

1002 The sum of gcd

学了莫队补的。基本还是别人的方法。

先预处理出每个点左右的gcd区间。最多log(a[i])个。

然后套莫队转移。

  1 # include <iostream>
  2 # include <cstdio>
  3 # include <vector>
  4 # include <algorithm>
  5 # include <cmath>
  6 using namespace std;
  7 typedef long long LL;
  8 const int maxn=10000+10;
  9 int n,Q,block,a[maxn];
 10 LL ans[maxn];
 11 
 12 struct node
 13 {
 14     int no,l,r,gcd;
 15 } query[maxn];
 16 vector <node> Lgcd[maxn],Rgcd[maxn];
 17 
 18 bool cmp(node a,node b)
 19 {
 20     if(a.l/block!=b.l/block) return a.l/block<b.l/block;
 21     return a.r<b.r;
 22 }
 23 
 24 int gcd(int a,int b)
 25 {
 26     return a%b?gcd(b,a%b):b;
 27 }
 28 
 29 void Init(void)
 30 {
 31     scanf("%d",&n);
 32     for(int i=1;i<=n;i++)
 33     {
 34         scanf("%d",a+i);
 35         Lgcd[i].clear();
 36         Rgcd[i].clear();
 37     }
 38     scanf("%d",&Q);
 39     for(int i=1;i<=Q;i++)
 40     {
 41         scanf("%d%d",&query[i].l,&query[i].r);
 42         query[i].no=i;
 43     }
 44     block=sqrt(n);
 45     sort(query+1,query+1+Q,cmp);
 46     return;
 47 }
 48 
 49 void PrePro(void)
 50 {
 51     for(int i=1;i<=n;i++)
 52     {
 53         int pos=i,tem_gcd=a[i];
 54         for(int j=0;j<Lgcd[i-1].size();j++)
 55         {
 56             node tem=Lgcd[i-1][j];
 57             int t=gcd(tem.gcd,tem_gcd);
 58             if(t!=tem_gcd)Lgcd[i].push_back(node{0,pos,0,tem_gcd});
 59             pos=tem.l,tem_gcd=t;
 60         }
 61         Lgcd[i].push_back(node{0,pos,0,tem_gcd});
 62     }
 63     Rgcd[n+1].clear();
 64     for(int i=n;i>=1;i--)
 65     {
 66         int pos=i,tem_gcd=a[i];
 67         for(int j=0;j<Rgcd[i+1].size();j++)
 68         {
 69             node tem=Rgcd[i+1][j];
 70             int t=gcd(tem.gcd,tem_gcd);
 71             if(t!=tem_gcd)Rgcd[i].push_back(node{0,0,pos,tem_gcd});
 72             pos=tem.r,tem_gcd=t;
 73         }
 74         Rgcd[i].push_back(node{0,0,pos,tem_gcd});
 75     }
 76     return;
 77 }
 78 
 79 void Solve(void)
 80 {
 81     LL res=0;
 82     int l=1,r=0;
 83     for(int i=1;i<=Q;i++)
 84     {    
 85         while(r<query[i].r)
 86         {
 87             int pos=++r;
 88             for(int j=0;j<Lgcd[r].size();j++)
 89             {
 90                 node tem=Lgcd[r][j];
 91                 if(tem.l>=l){res+=(LL)(pos-tem.l+1)*(LL)tem.gcd; pos=tem.l-1;}
 92                 else {res+=(LL)(pos-l+1)*(LL)tem.gcd; break;}
 93             }
 94         }
 95         for(;r>query[i].r;r--)
 96         {
 97             int pos=r;
 98             for(int j=0;j<Lgcd[r].size();j++)
 99             {
100                 node tem=Lgcd[r][j];
101                 if(tem.l>=l){res-=(LL)(pos-tem.l+1)*(LL)tem.gcd; pos=tem.l-1;}
102                 else {res-=(LL)(pos-l+1)*(LL)tem.gcd; break;}
103             }
104         }
105         while(l>query[i].l)
106         {
107             int pos=--l;
108             for(int j=0;j<Rgcd[l].size();j++)
109             {
110                 node tem=Rgcd[l][j];
111                 if(tem.r<=r){res+=(LL)(tem.r-pos+1)*(LL)tem.gcd; pos=tem.r+1;}
112                 else {res+=(LL)(r-pos+1)*(LL)tem.gcd; break;}
113             }
114         }
115         for(;l<query[i].l;l++)
116         {
117             int pos=l;
118             for(int j=0;j<Rgcd[l].size();j++)
119             {
120                 node tem=Rgcd[l][j];
121                 if(tem.r<=r){res-=(LL)(tem.r-pos+1)*(LL)tem.gcd; pos=tem.r+1;}
122                 else {res-=(LL)(r-pos+1)*(LL)tem.gcd; break;}
123             }            
124         }
125         ans[query[i].no]=res;
126     }
127     return;
128 }
129 
130 int main(void)
131 {
132     int T; cin>>T;
133     while(T--)
134     {
135         Init();
136         PrePro();
137         Solve();
138         for(int i=1;i<=Q;i++) printf("%I64d\n",ans[i]);
139     }
140     return 0;
141 }
Aguin

 

 

1003 GCD?LCM!

 

1004 Yu-Gi-Oh!

 

1005 Danganronpa

 

1006 The path

从1一开始往大的数BFS。搜到没路为止。

dis就是以1间隔递增。

再从n反向搜回来。一样操作。

因为保证有解。所以两遍一定搜完所有点。

对于所有u到v的边。如果dis[u]>dis[v]那么这条边肯定不走。置为最大值n即可。

否则把边置为dis[v]-dis[u]就符合要求了。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 # define maxn 100100
 6 int cnt,headlist[maxn],dis[maxn];
 7 
 8 struct node
 9 {
10     int to,pre,val;
11 } edge[maxn];
12 
13 void add(int from,int to)
14 {
15     cnt++;
16     edge[cnt].pre=headlist[from];
17     edge[cnt].to=to;
18     headlist[from]=cnt;
19 }
20 
21 int main(void)
22 {
23     int T; cin>>T;
24     while(T--)
25     {
26         cnt=0;
27         memset(headlist,0,sizeof(headlist));
28         memset(dis,-1,sizeof(dis));
29         int n,m; scanf("%d%d",&n,&m);
30         for(int i=1;i<=m;i++)
31         {
32             int u,v;
33             scanf("%d%d",&u,&v);
34             add(u,v);
35         }
36         dis[1]=0;
37         int l=1,r=n,pos;
38         for(int i=1;i<=n;i++)
39         {
40             if(dis[l]>=0) pos=l++;
41             else pos=r--;
42             dis[pos]=i;
43             for(int j=headlist[pos];j;j=edge[j].pre)
44             {
45                 int to=edge[j].to;
46                 if(dis[to]>=0) continue;
47                 dis[to]=0;
48             }
49         }
50         for(int i=1;i<=n;i++)
51             for(int j=headlist[i];j;j=edge[j].pre)
52                 edge[j].val=dis[edge[j].to]>dis[i]?dis[edge[j].to]-dis[i]:n;
53         for(int i=1;i<=m;i++) printf("%d\n",edge[i].val);
54     }
55     return 0;
56 }
Aguin

 

 

1007 Cover

只要不是那么暴力的暴力应该就- -。

 1 # include <iostream>
 2 # include <cstdio>
 3 using namespace std;
 4 int map[101][101],ans[501];
 5 
 6 struct node
 7 {
 8     int type,num,col,used;
 9 } op[501];
10 
11 int main(void)
12 {
13     int T; cin>>T;
14     while(T--)
15     {
16         int n,m; scanf("%d%d",&n,&m);
17         for(int t=0;t<2;t++)
18             for(int i=1;i<=n;i++)
19                 for(int j=1;j<=n;j++)
20                     scanf("%d",&map[i][j]);
21         for(int i=1;i<=m;i++)
22         {
23             char s[5];
24             scanf("%s",s);
25             if(s[0]=='L') op[i].type=0;
26             else op[i].type=1;
27             scanf("%d%d",&op[i].num,&op[i].col);
28             op[i].used=0;
29         }
30         int cnt=m;
31         while(cnt)
32         {
33             for(int i=1;i<=m;i++)
34             {
35                 if(!op[i].used)
36                 {
37                     int ok=1;
38                     if(op[i].type)
39                     {
40                         int x=op[i].num,c=op[i].col;
41                         for(int j=1;j<=n;j++) 
42                             if(map[x][j]&&map[x][j]!=c)
43                                 {ok=0;break;}
44                         if(ok)
45                         {
46                             op[i].used=1;
47                             ans[cnt--]=i;
48                             for(int j=1;j<=n;j++) map[x][j]=0;
49                             for(int j=1;j<=m;j++)
50                                 if(op[j].type&&!op[j].used&&op[j].num==x)
51                                 {
52                                     op[j].used=1;
53                                     ans[cnt--]=j;
54                                 }
55                         }
56                     }
57                     else
58                     {
59                         int x=op[i].num,c=op[i].col;
60                         for(int j=1;j<=n;j++) 
61                             if(map[j][x]&&map[j][x]!=c)
62                                 {ok=0;break;}
63                         if(ok)
64                         {
65                             op[i].used=1;
66                             ans[cnt--]=i;
67                             for(int j=1;j<=n;j++) map[j][x]=0;
68                             for(int j=1;j<=m;j++)
69                                 if(!op[j].type&&!op[j].used&&op[j].num==x)
70                                 {
71                                     op[j].used=1;
72                                     ans[cnt--]=j;
73                                 }
74                         }
75                     }    
76                 }
77             }
78         }
79         for(int i=1;i<=m;i++) printf("%d ",ans[i]);
80         puts("");
81     }
82     return 0;
83 }
Aguin

 

 

1008 Clock

枚举所有时刻指针夹角即可。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 
 6 struct node
 7 {
 8     int h,m,s,a1,a2,b1,b2,c1,c2;
 9 } Time[44000];
10 
11 void ans_print(int h,int m,int s)
12 {
13     int index=3600*h+60*m+s;
14     if(Time[index].a2==1) printf("%d ",Time[index].a1);
15     else printf("%d/%d ",Time[index].a1,Time[index].a2);
16     if(Time[index].b2==1) printf("%d ",Time[index].b1);
17     else printf("%d/%d ",Time[index].b1,Time[index].b2);
18     if(Time[index].c2==1) printf("%d ",Time[index].c1);
19     else printf("%d/%d ",Time[index].c1,Time[index].c2);
20     printf("\n");
21     return;
22 }
23 
24 void Init(void)
25 {
26     for(int h=0;h<12;h++)
27     {
28         for(int m=0;m<60;m++)
29         {
30             for(int s=0;s<60;s++)
31             {
32                 int index=3600*h+60*m+s;
33     
34                 int as=s*720;
35                 int am=720*m+12*s;
36                 int ah=3600*h+60*m+s;
37 
38                 int a1=max(ah,am)-min(ah,am);
39                 if(a1>21600) a1=43200-a1;
40                 int a2=120;
41                 while(a1%2==0&&a2%2==0){a1/=2;a2/=2;}
42                 while(a1%3==0&&a2%3==0){a1/=3;a2/=3;}
43                 while(a1%5==0&&a2%5==0){a1/=5;a2/=5;}
44 
45                 int b1=max(ah,as)-min(ah,as);
46                 if(b1>21600) b1=43200-b1;
47                 int b2=120;
48                 while(b1%2==0&&b2%2==0){b1/=2;b2/=2;}
49                 while(b1%3==0&&b2%3==0){b1/=3;b2/=3;}
50                 while(b1%5==0&&b2%5==0){b1/=5;b2/=5;}
51 
52                 int c1=max(as,am)-min(as,am);
53                 if(c1>21600) c1=43200-c1;
54                 int c2=120;
55                 while(c1%2==0&&c2%2==0){c1/=2;c2/=2;}
56                 while(c1%3==0&&c2%3==0){c1/=3;c2/=3;}
57                 while(c1%5==0&&c2%5==0){c1/=5;c2/=5;}
58 
59                 Time[index].h=h;
60                 Time[index].m=m;
61                 Time[index].s=s;
62                 Time[index].a1=a1;
63                 Time[index].a2=a2;
64                 Time[index].b1=b1;
65                 Time[index].b2=b2;
66                 Time[index].c1=c1;
67                 Time[index].c2=c2;
68             }
69         }
70     }
71     return;
72 }
73 
74 int main(void)
75 {
76     Init();
77     int T ;cin>>T;
78     while(T--)
79     {
80         int h,m,s;
81         scanf("%d",&h);
82         if(h>=12) h-=12;
83         getchar();
84         scanf("%d",&m);
85         getchar();
86         scanf("%d",&s);
87         ans_print(h,m,s);
88     }
89     return 0;
90 }
Aguin

 

 

1009 Geometer's Sketchpad

 

1010 Zero Escape

dp题。

定义状态:dp[i][j]为前i个人中选至少一个人(取的人数小于等于i即可)。使得dr=j的情况数。

转移:dp[i][j]=dp[i-1][(j-num+8)%9+1]+dp[i-1][j],dp[i][num]++。

i-1个人(j-num+8)%9+1的情况加上第i个num正好凑成j。再加上不选择第i个人的情况。最后再考虑只取第i个人的情况。

对9取模后。如果sum等于A+B的话。说明可以组合成两道门都走的情况。

但是这里注意前面dp定义的是至少选一个人的情况。如果B=sum。就存在全部走B不走A的情况。

所以答案是dp[n][A]+(B==sum)或者dp[n][B]+(A==sum)也一样。

如果sum不等于A+B。那么最多选择一扇门走完。

判断能否走A。能否走B。即可。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const int maxn=101000;
 7 const LL mod=258280327;
 8 LL dp[maxn][10];
 9 
10 int main(void)
11 {
12     int T; cin>>T;
13     while(T--)
14     {
15         int n,A,B,num;
16         scanf("%d%d%d",&n,&A,&B);
17         int sum=0;
18         for(int i=1;i<=n;i++)
19         {
20             scanf("%d",&num);
21             sum+=num;
22             for(int j=1;j<=9;j++) dp[i][j]=(dp[i-1][(j-num+8)%9+1]+dp[i-1][j])%mod;
23             dp[i][num]=(dp[i][num]+(LL)1)%mod;
24         }
25         sum=(sum-1)%9+1;
26         if(sum==(A+B-1)%9+1) printf("%I64d\n",(dp[n][A]+(LL)(B==sum))%mod);
27         else printf("%d\n",(sum==A)+(sum==B));
28     }
29     return 0;
30 }
Aguin

 

 

1011 tree

posted @ 2015-08-13 22:59  Aguin  阅读(300)  评论(0编辑  收藏  举报