2015 Multi-University Training Contest 3
1002 / HDU 5317 RGCDQ
题目大意:定义f(n)为n素因子的种类数,比如12=3*2*2有2和3两类素因子,给定l r求max{f(i),f(j)} (l<=i<j<=r)
思路:关键就是,2*3*5*7*11*13*17=510510再乘19就爆了,所以f(n)小于等于7!!!只要记录,这7个数在这个区间里分别出现了多少次,然后暴力扫7个数组合的gcd的最大值即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define N 1000009 5 #define maxn 2000009 6 using namespace std; 7 int gcd(int x,int y) 8 { 9 if(x==0)return y; 10 return gcd(y%x,x); 11 } 12 int visit[maxn],sum[maxn][8]; 13 int main() 14 { 15 int t; 16 for(int i=2;i<=N;i++) 17 { 18 if(!visit[i]) 19 { 20 visit[i]=1; 21 for(int j=2;j*i<=N;j++) 22 { 23 visit[i*j]++; 24 } 25 } 26 for(int j = 1;j<=7;j++)sum[i][j]=sum[i-1][j]; 27 sum[i][visit[i]]++; 28 } 29 scanf("%d",&t); 30 while(t--) 31 { 32 int l,r; 33 int vis[10]={0}; 34 scanf("%d%d",&l,&r); 35 for(int i=1;i<=7;i++) 36 { 37 if(sum[r][i]-sum[l-1][i]==1)vis[i]=1; 38 else if(sum[r][i]-sum[l-1][i]>1)vis[i]=2; 39 // printf("%d ",vis[i]); 40 } 41 //puts(""); 42 int ans = 1; 43 for(int i=1;i<=7;i++)if(vis[i]) 44 { 45 for(int j=1;j<i;j++)if(vis[j]) 46 { 47 ans = max(ans, gcd(i,j)); 48 } 49 } 50 for(int i=1;i<=7;i++)if(vis[i]==2) 51 { 52 ans = max(ans , i); 53 } 54 printf("%d\n",ans); 55 } 56 return 0; 57 }
1004 /HDU 5319 Painter:
题目大意:给一个N行的矩形,每次可以按/方向刷蓝色,按\方向刷红色,两种颜色相遇时变成绿色,问最从一个空矩形开始最少刷多少次可以得到目标矩形
思路:直接模拟,遇到R就把一\行全部刷玩遇到B和G同理
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define maxn 100 5 #define ll long long 6 #define LLD "%lld" 7 using namespace std; 8 int a[maxn],m,n; 9 char ch[maxn][maxn]; 10 int work(int x,int y) 11 { 12 int tx = x, ty = y; 13 if(ch[x][y]=='R') 14 { 15 while(x<=n && y<=m) 16 { 17 if(ch[x][y]=='R') 18 { 19 ch[x][y]='.'; 20 } 21 else if(ch[x][y]=='G') 22 { 23 ch[x][y]='B'; 24 } 25 else break; 26 x++; 27 y++; 28 } 29 x = tx-1; 30 y = ty-1; 31 while(x>=1 && y>=1) 32 { 33 if(ch[x][y]=='R') 34 { 35 ch[x][y]='.'; 36 } 37 else if(ch[x][y]=='G') 38 { 39 ch[x][y]='B'; 40 } 41 else break; 42 x--; 43 y--; 44 } 45 return 1; 46 } 47 if(ch[x][y]=='B') 48 { 49 while(x<=n && y>=1) 50 { 51 if(ch[x][y]=='B') 52 { 53 ch[x][y]='.'; 54 } 55 else if(ch[x][y]=='G') 56 { 57 ch[x][y]='R'; 58 } 59 else break; 60 x++; 61 y--; 62 } 63 x=tx-1; 64 y = ty+1; 65 while(x>=1 && y<=m) 66 { 67 if(ch[x][y]=='B') 68 { 69 ch[x][y]='.'; 70 } 71 else if(ch[x][y]=='G') 72 { 73 ch[x][y]='R'; 74 } 75 else break; 76 x--; 77 y++; 78 } 79 return 1; 80 } 81 if(ch[x][y]=='G') 82 { 83 while(x<=n && y<=m) 84 { 85 if(ch[x][y]=='R') 86 { 87 ch[x][y]='.'; 88 } 89 else if(ch[x][y]=='G') 90 { 91 ch[x][y]='B'; 92 } 93 else break; 94 x++; 95 y++; 96 } 97 x = tx-1; 98 y = ty-1; 99 while(x>=1 && y>=1) 100 { 101 if(ch[x][y]=='R') 102 { 103 ch[x][y]='.'; 104 } 105 else if(ch[x][y]=='G') 106 { 107 ch[x][y]='B'; 108 } 109 else break; 110 x--; 111 y--; 112 } 113 x=tx,y=ty; 114 while(x<=n && y>=1) 115 { 116 if(ch[x][y]=='B') 117 { 118 ch[x][y]='.'; 119 } 120 else if(ch[x][y]=='G') 121 { 122 ch[x][y]='R'; 123 } 124 else break; 125 x++; 126 y--; 127 } 128 x=tx-1; 129 y = ty+1; 130 while(x>=1 && y<=m) 131 { 132 if(ch[x][y]=='B') 133 { 134 ch[x][y]='.'; 135 } 136 else if(ch[x][y]=='G') 137 { 138 ch[x][y]='R'; 139 } 140 else break; 141 x--; 142 y++; 143 } 144 return 2; 145 } 146 } 147 int main() 148 { 149 int t; 150 scanf("%d",&t); 151 while(t--) 152 { 153 scanf("%d",&n); 154 for(int i=1;i<=n;i++) 155 { 156 scanf("%s",ch[i]+1); 157 } 158 m = strlen(ch[1]+1); 159 int ans =0; 160 for(int i=1;i<=n;i++) 161 { 162 for(int j=1;j<=m;j++) 163 { 164 if(ch[i][j]!='.') 165 { 166 ans += work(i,j); 167 } 168 } 169 } 170 printf("%d\n",ans); 171 } 172 return 0; 173 }
1008 /HDU 5323 Solve this interesting problem
题目大意:给定一个区间[l,r],问是否可能是线段树上的一个区间
思路:由于线段树除了最后一层,几乎是完全二叉数,所以树高很小,可以直接爆搜所有情况,注意这题很坑!r+(r-l)+1<ans 这个剪枝换成r+(r-l)+1<=ans就re 心中是千万条草你妈奔过啊
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 long long a,b,ans; 7 void dfs(long long l,long long r) 8 { 9 if(l==0) 10 { 11 ans = min(ans,r); 12 return; 13 } 14 if(r > ans || r-l+1 > l)return; 15 if(l-1-(r-l)>=0)dfs(2*l-1-(r),r); 16 if(l-1-(r-l+1)>=0)dfs(l-1-(r-l+1),r); 17 if(r+(r-l)<ans)dfs(l,r+(r-l)); 18 if(r+(r-l)+1<ans)dfs(l,r+(r-l)+1); 19 } 20 int main() 21 { 22 while(scanf("%lld%lld",&a,&b)!=EOF) 23 { 24 ans = 1LL<<59; 25 dfs(a,b); 26 if(ans!=1LL<<59)printf("%lld\n",ans);else puts("-1"); 27 } 28 return 0; 29 }
1010 / HDU 5325 crazy bobo
题目大意:给一棵树,每个节点有个权值w,要找到一些点u1 u2 u3.......使得w[u1]<w[u2]<w[u3]..并且对于ui u(i+1)路径上不存在一个点X使得w[x]>=w[ui]
思路:有点玄学的题,比赛时想到先排序然后T了,比赛后想了想xiaoxin的并查集做法想到了一个更神奇的做法,从大到小排序,对于每个点找相邻点中形成最大的集合数,累加来更新自己这个点的最大集合数,TUT要是再等一等比赛能少TLE一发的
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 1000009 6 #define ll long long 7 #define LLD "%lld" 8 using namespace std; 9 struct T 10 { 11 int w; 12 int id; 13 }a[maxn]; 14 int nex[maxn],point[maxn],head[maxn],b[maxn],ww[maxn]; 15 int n,x,y,now,st[maxn],h,father[maxn],cnt[maxn]; 16 int cmp(T a,T b) 17 { 18 return a.w<b.w; 19 } 20 void add(int x,int y) 21 { 22 nex[++now] = head[x]; 23 head[x] = now; 24 point[now] = y; 25 } 26 int find(int x) 27 { 28 if(father[x]==x)return x; 29 return father[x] = find(father[x]); 30 } 31 int main() 32 { 33 while(scanf("%d",&n)!=EOF) 34 { 35 now = 0; 36 memset(head,0,sizeof(head)); 37 for(int i=1;i<=n;i++) 38 { 39 father[i]=i; 40 cnt[i]=1; 41 scanf("%d",&a[i].w); 42 ww[i] = a[i].w; 43 a[i].id = i; 44 } 45 sort(a+1,a+1+n,cmp); 46 for(int i=1;i<n;i++) 47 { 48 scanf("%d%d",&x,&y); 49 add(x,y); 50 add(y,x); 51 } 52 int ans = 0; 53 for(int i=n;i>=1;i--) 54 { 55 int u = a[i].id,an=0; 56 for(int j = head[u];j;j=nex[j]) 57 { 58 int v = point[j]; 59 if(ww[v]>=ww[u])an+=b[v]; 60 } 61 b[u] = an+1; 62 ans = max(b[u],ans); 63 } 64 printf("%d\n",ans); 65 } 66 return 0; 67 }
1011 / HDU 5326 work
题目大意:给一棵树,问你有多少点的子树正好有K个节点
思路:大水题,直接dfs即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define maxn 100009 5 #define ll long long 6 #define LLD "%lld" 7 using namespace std; 8 int nex[maxn],head[maxn],point[maxn],now,ans; 9 int n,k,x,y,in[maxn]; 10 void add(int x,int y) 11 { 12 nex[++now] = head[x]; 13 head[x] = now; 14 point[now] = y; 15 } 16 int dfs(int x,int k) 17 { 18 int ret = 1; 19 for(int i=head[x];i;i=nex[i]) 20 { 21 int u = point[i]; 22 ret+=dfs(u,k); 23 } 24 if(ret-1==k) 25 { 26 ans++; 27 } 28 return ret; 29 } 30 int main() 31 { 32 int t; 33 while(scanf("%d%d",&n,&k)!=EOF) 34 { 35 now = 0 ; 36 memset(in,0,sizeof(in)); 37 memset(head,0,sizeof(head)); 38 for(int i=1;i<n;i++) 39 { 40 scanf("%d%d",&x,&y); 41 add(x,y); 42 in[y]++; 43 } 44 ans=0; 45 for(int i=1;i<=n;i++)if(in[i]==0) 46 { 47 dfs(i,k); 48 } 49 printf("%d\n",ans); 50 } 51 return 0; 52 }