您的位置:首页 > 大数据 > 人工智能

2015 Multi-University Training Contest 4

2015-07-30 16:41 429 查看
官方题解:2015 Multi-University Training Contest 4 solutions BY 学军中学

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;
}


(待续。。。)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多校联合训练