这个题简直不要太简单,我在考场门口堵到他们,听他们描述完之后,我的第一反应是不信的,但他们说难得一批,怎么都得不到全解,我当时就断定,他们十几个人肯定记错题了,怎么可能这么简单。 晚上八点钟左右我拿到原题,我疯了都快,怎么能只拿低保,他最多只有八组数啊,每组有81种可能,总共才648种可能。648种可能,它就是台286,1s它也能跑完,它就是648个馒头,也不够我吃一年!!!!!!!!!!!!!这题简单到我都不相信有优化算法,因为我懒得去想!!!!! ------------------发泄完毕------------------- 回到正题,这题用暴力方法完全足够,每一组有81种可能,把81种可能转化成五位十进制数,存到对应的堆里面。 如果只有一组数据,特判一下,答案就是81,1~3点,15分到手。 如果有多组数据,为每一组开一个堆,存各自的81种答案,然后把堆顶拿出来比较:(1)如果堆顶一样,答案数++,然后把所有堆顶都踢掉;(2)如果有堆顶不一样,那就踢掉堆顶最大的那个堆顶(默认大根堆),再比较。 我没优化的代码是O(1e5),能够做点优化,比如五组数分别比较一下子,如果任意两组数不一样的数据位数超过3,没答案;有2位数据不一样但不相邻,没答案;堆pop()的时候,盯住相邻的某个堆,一直踢到不比相邻的堆顶大,这样可以一次踢好几个数,我没写,因为本来就648个数,一次踢一个完全来的及。上面的优化我都没写,因为写完题解,我还要忙着去清!理!门!户!散会!!!! ```cpp #include<bits/stdc++.h> using namespace std;
int n,tem,res; priority_queue q[10];
void kick(int n){ int x=0,pos=0; for(int i=1;i<=n;i++){ if(q[i].top()>x){ x=q[i].top(); pos=i; } } q[pos].pop(); }
void kickall(int n){ for(int i=1;i<=n;i++){ q[i].pop(); } }
int main(){ cin>>n; if(n==1){ cout<<81; return 0; } for(int i=1;i<=n;i++){ int a,b,c,d,e; cin>>a>>b>>c>>d>>e; for(int j=1;j<=9;j++){ tem=(a+j)%1010000+b1000+c100+d10+e; q[i].push(tem); tem = a10000+(b+j)%101000+c100+d10+e; q[i].push(tem); tem = a10000+b1000+(c+j)%10100+d10+e; q[i].push(tem); tem = a10000+b1000+c100+(d+j)%1010+e; q[i].push(tem); tem = a10000+b1000+c100+d10+(e+j)%10; q[i].push(tem); tem = (a+j)%1010000+(b+j)%101000+c100+d10+e; q[i].push(tem); tem = a10000+(b+j)%101000+(c+j)%10100+d10+e; q[i].push(tem); tem = a10000+b1000+(c+j)%10100+(d+j)%1010+e; q[i].push(tem); tem = a10000+b1000+c100+(d+j)%1010+(e+j)%10; q[i].push(tem);
}
}
bool flag=true;
while(flag){
for(int i=1;i<=n;i++){
if(q[i].empty()){
flag=false;
break;
}
}
if(!flag){
break;
}
bool st=true;
for(int i=1;i<n;i++){
if(q[i].top()!=q[i+1].top()){
kick(n);
st=false;
break;
}
}
if(st){
res++;
kickall(n);
}
}
cout<<res;
return 0;
}