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

2013 Multi-University Training Contest 7

2013-08-14 18:36 429 查看
1001 Hyperspace

求最远曼哈顿距离,求曼哈顿距离并不难,难的是这题需要求n次,而且其中有删点,k维空间。。。

虽然比赛时没有AC,但也想到了枚举2^k种情况+-得到最远曼哈顿距离的方法,可是由于没想到用stl里的set,multiset,map等处理删点问题,导致复杂度一直为O(n^2*k*2^k)

之后看了标程才知道了原来可以去掉n次。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#define mem(a,b) memset(a,b,sizeof(a))
#define INF 1e9
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int a[60001][10];
multiset<int>t[32];
multiset<int>::iterator it;
int main()
{
int n,k,i,j,q,sum,op,x,t1,t2,ans;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(i=0; i<(1<<k); i++)
{
t[i].clear();
}
for(i=1; i<=n; i++)
{
RD(op);
if(op==0)
{
for(j=0; j<k; j++)
{
scanf("%d",&a[i][j]);
}
for(j=0; j<(1<<k); j++)
{
sum=0;
for(q=0; q<k; q++)//就是这里,我本来是一个for(0-n),用二维数组保存,和用multiset查找,去重,删点
{
if(j&(1<<q))
{
sum+=a[i][q];
}
else
{
sum-=a[i][q];
}
}
t[j].insert(sum);
}
}
else
{
RD(x);
for(j=0; j<(1<<k); j++)
{
sum=0;
for(q=0; q<k; q++)
{
if(j&(1<<q))
{
sum+=a[x][q];
}
else
{
sum-=a[x][q];
}
}
it=t[j].find(sum);
t[j].erase(it);
}
}
ans=0;
for(j=0; j<(1<<k); j++)//最后直接两两相减就成
{
it=t[j].end();
it--;
t1=(*it);
it=t[j].begin();
t2=(*it);
ans=max(ans,t1-t2);
}
OT(ans);
printf("\n");
}
}
return 0;
}

1004 Mutiples on a circle

一道环形的DP题,卡时间卡得很紧,所以时间复杂度只能为O(n*k)

t[i][j]代表第i元素结尾,j为余数的种数。3倍延长环去计算。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int f[50001],s[50001],e[150001],t[50001][201];
int main()
{
int n,mod,l,w,sum,ans,num,i,j;
while(scanf("%d%d",&n,&mod)!=EOF)
{
e[0]=1;
memset(t,0,sizeof(int)*n*201);//注意初始化t时一定要这样写,不然会TLE到死。
for(i=1; i<n*3; i++)
{
e[i]=e[i-1]*10%mod;
}
for(i=0; i<n; i++)
{
RD(f[i]);
num=f[i];
if(f[i]==0)
{
ans=1;
}
else{
ans=0;
while(num)
{
ans++;
num/=10;
}
}
s[i]=ans;
}
f
=f[0];
s
=s[0];
sum=0;
l=0;
w=0;
for(i=n; i>0; i--)
{
sum=(sum+f[i]*e[l])%mod;
l+=s[i];
t[0][sum]++;
}
w+=t[0][0];
for(i=1; i<n; i++)
{
for(j=0; j<mod; j++)
{
t[i][(j*e[s[i]]+f[i])%mod]+=t[i-1][j];//状态转移方程
}
sum=(sum*e[s[i]]+f[i])%mod;
t[i][sum]--;
t[i][f[i]%mod]++;
sum=((sum-f[i]*e[l])%mod+mod)%mod;//sum-f[i]*e[l]有可能为负值且绝对值远小于mod,所以需要这样取余。
w+=t[i][0];
}
OT(w);
printf("\n");
}
return 0;
}

1006 Backup Plan
简单构造题。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int main()
{
int n,m,i,j,k,a[105],w;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<n&&i<m;++i)
{
w=n-1;
for(j=i;j<m;j+=n,w=(w-1+n)%n)
{
if(w==i)
{
w=(w-1+n)%n;
}
a[j]=w;
}
}
for(i=0;i<m;++i)
{
printf("%d %d",i%n+1,a[i]+1);
for(j=0;j<n;++j)
{
if(j!=i%n&&j!=a[i])
{
printf(" %d",j+1);
}
}
printf("\n");
}
}
return 0;
}

1007 Present Day, Present Time
神奇的博弈,涉及到dp的部分处理,当时比赛时一直在想这题,但一直没想法。看了solution后才了解,是很简单的一个思想。

由于回收站的使用次数是不受限制的,所以各个回收站的容量的组合代表的数就是能被一次性回收掉的石子数量,而由于Bi的数量最多只有100,回收站的个数最多也只有100,所以当一次性使用所有回收站且只使用一次,那一次性最多回收10000个石子。接下去要求的是各堆石子最多能拿几次拿光,如果有不能拿光就直接判输,得到的各堆数量就简化成了一个NIM博弈,直接异或一遍,然后就可以判输赢就行。这题还有一个地方需要注意就是当Ai大于10000时,由于要求的是最多取的次数,所以之后就是循环min(Bi)。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int sg[10005],a[100005],b;
int main()
{
int n,m,i,j,ans,sum,f,w;
char x[11],y[11];
while(scanf("%d%d%s%s",&n,&m,x,y)!=EOF)
{
for(i=0; i<n; ++i)
{
RD(a[i]);
}
mem(sg,-1);
sg[0]=0;
ans=101;
for(i=0; i<m; ++i)
{
RD(b);
ans=min(ans,b);
for(j=0; j+b<10001; ++j)//dp过程
{
if(sg[j]>=0)
{
sg[j+b]=max(sg[j+b],sg[j]+1);//每次求最多取的次数
}
}
}
sum=0;
f=0;
for(i=0; i<n; ++i)
{
w=a[i];
if(w<=10000)
{
if(sg[w]<0)
{
f=1;
}
sum^=sg[w];
}
else
{
w=(w-10000+ans)%ans+10000-ans;//之后循环节就是ans
if(sg[w]<0)
{
f=1;
}
sum^=sg[w]+(a[i]-w)/ans;
}
}
if(f==0&&sum!=0)
{
printf("%s\n",x);
}
else
{
printf("%s\n",y);
}
}
return 0;
}

我们好水,这次收获也算大。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU 多校