2015 Multi-University Training Contest 4
2015-07-30 16:41
429 查看
官方题解:2015 Multi-University Training Contest 4 solutions BY 学军中学
题意:每次询问\([a,b](a\leqslant b)\)中有多少个 beautiful number, beautiful number指每位数字不同
\( 1\leqslant T\leqslant 1000,1\leqslant a\leqslant b\leqslant 10^5\)
因为范围比较小,可以直接暴力预处理出[1,n]内beautiful number的数量。
[a,b]=[1,a]-[1,b-1]
题意:求出最长的等差数列和等比数列,答案取两者长度大的
\(1\leqslant n\leqslant 10^6\)
随便YY一发就能过。
题意:知道一个序列的不同的连续字串个数K,求构造满足K的任意一个序列
\(1\leqslant K\leqslant 10^9\),序列长度\(1\leqslant K\leqslant 10^5\)
因为序列长度\(n\)的最大范围小于\(K\),所以不能用全填\(1\)的方法
如果序列为这种形式:\(1,\cdots ,1,2\cdots,2,3,\cdots,3,\cdots,t\)
设\(n\)为序列长度,\(L_i\)为数\(i\)出现的次数,那么序列的不同的连续字串个数
$$K=\frac{n^2+n-\sum_{i=1}^{t}L_i(L_i-1)}{2}$$
可以列出下面的方程
$$\left\{\begin{matrix}
\sum_{i=1}^{t}L_i(L_i-1)=n^2+n-2k\\
\sum_{i=1}^{t}L_i=n
\end{matrix}\right.$$
设\(\sum_{i=1}^{t}L_i(L_i-1)=d\),那么可以用二分找出最大的\(p\)使\(p(p-1)\leqslant d\),然后\(L_1\)可以取\(p\)
此时另\(d=d-p(p-1)\),又可以用上面的方法求出所有\(L_i\)。因为\(d\)一定为偶数,所以最后一定能让\(d=0\)
因为\(d=n^2+n-2k\),所以需要用二分找到最小的\(n\)满足\(n^2+n-2k\geqslant 0\)
如果最后满足 \(\sum_{i=1}^{t}L_i=n \),那么便是一个解。
通过打表发现不满足的只有\(k=4\)和\(k=16\)时,对于这两组直接全输出1就行
题意:在一个c*r的格子里,有一些水滴。一个大小大于4的水滴会向4个方向(上下左右)分裂成4个小水滴。小水滴会一直沿分裂方向运动,直到遇到水滴,使水滴大小加1,小水滴消失。现在给出一些水滴的坐标和大小。并在0s时在(x,y)处有一个水滴分裂。问Ts时所有水滴的状态
\(
1\leqslant r \leqslant100, 1\leqslant c\leqslant 100, 1\leqslant n\leqslant 100, 1\leqslant T\leqslant 10000 \)
因为数据范围较小,可以直接模拟整个过程。
有三点需要注意:
1、无论分裂前的水滴大小是多少,分裂后小水滴的大小始终是为1的。
2、0s时注意判断是否有水滴大小大于4,这些水滴在0s分裂。
3、水滴分裂后及时清除水滴的标记,此时水滴已经不存在
(待续。。。)
1001
HDU 5327:http://acm.hdu.edu.cn/showproblem.php?pid=5327题意:每次询问\([a,b](a\leqslant b)\)中有多少个 beautiful number, beautiful number指每位数字不同
\( 1\leqslant T\leqslant 1000,1\leqslant a\leqslant b\leqslant 10^5\)
因为范围比较小,可以直接暴力预处理出[1,n]内beautiful number的数量。
[a,b]=[1,a]-[1,b-1]
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<string> using namespace std; #define MAX(a,b) ((a>b)?(a):(b)) #define MIN(a,b) ((a<b)?(a):(b)) #define LL __int64 #define N 100005 #define INF 1<<30 int cnt ; int vis[10]; void init(){ memset(cnt,0,sizeof(cnt)); int t,flag; for(int i=1;i<=100000;++i){ t=i; flag=0; memset(vis,0,sizeof(vis)); while(t){ vis[t%10]++; if(vis[t%10]>1){ flag=1; break; } t/=10; } cnt[i]=cnt[i-1]; if(flag==0) cnt[i]++; } } int main(){ int T; scanf("%d",&T); init(); while(T--){ int a,b; scanf("%d%d",&a,&b); printf("%d\n",cnt-cnt[a-1]); } return 0; }
1002
[b]HDU 5328:http://acm.hdu.edu.cn/showproblem.php?pid=5328题意:求出最长的等差数列和等比数列,答案取两者长度大的
\(1\leqslant n\leqslant 10^6\)
随便YY一发就能过。
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<string> using namespace std; #define MAX(a,b) ((a>b)?(a):(b)) #define MIN(a,b) ((a<b)?(a):(b)) #define INF 0x3f3f3f3f #define ll __int64 #define N 1000010 int n; int a ; int dp [2]; int main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } dp[1][0]=dp[1][1]=1; for(int i=2;i<=n;i++) dp[i][0]=dp[i][1]=2; for(int i=3;i<=n;i++){ if(a[i]-a[i-1]==a[i-1]-a[i-2]) dp[i][0]=dp[i-1][0]+1; if(a[i]*1.0/a[i-1]==a[i-1]*1.0/a[i-2]) dp[i][1]=dp[i-1][1]+1; } int ans=0; for(int i=1;i<=n;i++){ ans=max(ans,max(dp[i][0],dp[i][1])); } printf("%d\n",ans); } return 0; }
1007
HDU 5334:http://acm.hdu.edu.cn/showproblem.php?pid=5334题意:知道一个序列的不同的连续字串个数K,求构造满足K的任意一个序列
\(1\leqslant K\leqslant 10^9\),序列长度\(1\leqslant K\leqslant 10^5\)
因为序列长度\(n\)的最大范围小于\(K\),所以不能用全填\(1\)的方法
如果序列为这种形式:\(1,\cdots ,1,2\cdots,2,3,\cdots,3,\cdots,t\)
设\(n\)为序列长度,\(L_i\)为数\(i\)出现的次数,那么序列的不同的连续字串个数
$$K=\frac{n^2+n-\sum_{i=1}^{t}L_i(L_i-1)}{2}$$
可以列出下面的方程
$$\left\{\begin{matrix}
\sum_{i=1}^{t}L_i(L_i-1)=n^2+n-2k\\
\sum_{i=1}^{t}L_i=n
\end{matrix}\right.$$
设\(\sum_{i=1}^{t}L_i(L_i-1)=d\),那么可以用二分找出最大的\(p\)使\(p(p-1)\leqslant d\),然后\(L_1\)可以取\(p\)
此时另\(d=d-p(p-1)\),又可以用上面的方法求出所有\(L_i\)。因为\(d\)一定为偶数,所以最后一定能让\(d=0\)
因为\(d=n^2+n-2k\),所以需要用二分找到最小的\(n\)满足\(n^2+n-2k\geqslant 0\)
如果最后满足 \(\sum_{i=1}^{t}L_i=n \),那么便是一个解。
通过打表发现不满足的只有\(k=4\)和\(k=16\)时,对于这两组直接全输出1就行
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<string> using namespace std; #define MAX(a,b) ((a>b)?(a):(b)) #define MIN(a,b) ((a<b)?(a):(b)) #define LL __int64 #define N 100005 #define INF 1<<30 int L ; int cnt; int main(){ LL k; LL n; while(~scanf("%I64d",&k)){ cnt=0; if(k==4||k==16){ printf("%d\n",k); while(k--){ printf("1"); if(k!=0)printf(" "); } printf("\n"); continue; } //cal min(n) :n^2+n-2k>=0 LL l=1,r=100000,m; while(l<=r){ m=(l+r)>>1; if(m*m+m-2*k>=0){ n=m; r=m-1; }else{ l=m+1; } } //cal L[] LL d=n*n+n-2*k; LL p; LL len=0; while(d||len<n){ l=1,r=100000; while(l<=r){ m=(l+r)>>1; if(m*(m-1)<=d){ p=m; l=m+1; }else{ r=m-1; } } if(p==0)p=1; L[++cnt]=(p?p:1); len+=p; d=d-p*(p-1); } printf("%I64d\n",n); int first=true; for(int i=1;i<=cnt;++i){ n-=L[i]; while(L[i]--){ if(!first)printf(" "); printf("%d",i); first=false; } } printf("\n"); } return 0; }
1010
HDU 5336:http://acm.hdu.edu.cn/showproblem.php?pid=5336题意:在一个c*r的格子里,有一些水滴。一个大小大于4的水滴会向4个方向(上下左右)分裂成4个小水滴。小水滴会一直沿分裂方向运动,直到遇到水滴,使水滴大小加1,小水滴消失。现在给出一些水滴的坐标和大小。并在0s时在(x,y)处有一个水滴分裂。问Ts时所有水滴的状态
\(
1\leqslant r \leqslant100, 1\leqslant c\leqslant 100, 1\leqslant n\leqslant 100, 1\leqslant T\leqslant 10000 \)
因为数据范围较小,可以直接模拟整个过程。
有三点需要注意:
1、无论分裂前的水滴大小是多少,分裂后小水滴的大小始终是为1的。
2、0s时注意判断是否有水滴大小大于4,这些水滴在0s分裂。
3、水滴分裂后及时清除水滴的标记,此时水滴已经不存在
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<string> using namespace std; #define MAX(a,b) ((a>b)?(a):(b)) #define MIN(a,b) ((a<b)?(a):(b)) #define LL __int64 #define N 105 #define INF 1<<30 struct node1 { int x,y; node1() {} node1(int _x,int _y) { x=_x; y=_y; } } wd ; struct node2 { int x,y,d; node2() {} node2(int _x,int _y,int _d) { x=_x; y=_y; d=_d; } }; int mpt ; int val ; int dir[4][2]= {0,1,1,0,0,-1,-1,0}; int ans ; int r,c,n,T; queue<node2> sd; vector<node2> temp; void init() { memset(mpt,0,sizeof(mpt)); memset(val,0,sizeof(val)); memset(ans,-1,sizeof(ans)); while(!sd.empty())sd.pop(); temp.clear(); } //判断是否超出边界 bool judge(node2 a) { if(a.x<1||a.x>r||a.y<1||a.y>c)return false; return true; } //判断当前位置是否为水滴 bool iswd(node2 a) { if(mpt[a.x][a.y])return true; return false; } //水滴分裂 void crack(int t) { for(int i=1; i<=n; ++i) { if(val[wd[i].x][wd[i].y]>4&&mpt[wd[i].x][wd[i].y]) { ans[i]=t; for(int j=0; j<4; ++j) temp.push_back(node2(wd[i].x,wd[i].y,j)); val[wd[i].x][wd[i].y]=4; mpt[wd[i].x][wd[i].y]=0; } } for(int i=0; i<temp.size(); ++i) sd.push(temp[i]); temp.clear(); } //模拟 void bfs(int sx,int sy) { node2 now,next; for(int i=0; i<4; ++i) sd.push(node2(sx,sy,i)); crack(0); val[sx][sy]=4; for(int t=1; t<=T; ++t) { while(!sd.empty()) { now=sd.front(); sd.pop(); next.x=now.x+dir[now.d][0]; next.y=now.y+dir[now.d][1]; next.d=now.d; val[now.x][now.y]--; if(!judge(next))continue; val[next.x][next.y]++; if(iswd(next))continue; temp.push_back(next); } crack(t); } } int main() { int x,y,s; while(scanf("%d%d%d%d",&r,&c,&n,&T)!=EOF) { init(); for(int i=1; i<=n; ++i) { scanf("%d%d%d",&x,&y,&s); mpt[x][y]=1; val[x][y]=s; wd[i]=node1(x,y); } scanf("%d%d",&x,&y); bfs(x,y); for(int i=1; i<=n; ++i) { if(ans[i]==-1) { printf("1 %d\n",val[wd[i].x][wd[i].y]); } else { printf("0 %d\n",ans[i]); } } } return 0; }
(待续。。。)
相关文章推荐
- 2015 Multi-University Training Contest 1
- HDU 6052 暴力计数
- HDU 6053 容斥dp 或 莫比乌斯反演
- HDU 6035 树形dp
- hdu 5288 思维技巧
- HDU 3530 RMQ+twopointer/单调队列
- 2015 Multi-University Training Contest 8
- 2015 Multi-University Training Contest 7
- 2015 Multi-University Training Contest 3
- 2015 Multi-University Training Contest 2
- 2015 Multi-University Training Contest 6
- 2015 Multi-University Training Contest 5
- HDU 6138 AC自动机
- HDU 6169 Senior PanⅡ 数论+DP
- hdu 6162 Ch’s gift【树链剖分】
- 2017 Multi-University Training Contest - Team 8
- 2017 Multi-University Training Contest - Team 7
- 2017 Multi-University Training Contest - Team 6
- 2017 Multi-University Training Contest - Team 5
- 2017 Multi-University Training Contest - Team 4