题意:给你n头奶牛,以及他们的周期产奶量,如果有一天只有一头奶牛产奶量最少,那么就杀掉这头牛,问最后有多少牛存活,并且最后杀死一头奶牛的时间。
思路:首先算出所有的周期的最小公倍数,如果这段时间内有奶牛被杀的话,那么重新计算,否则说明不会再有奶牛被杀。
AC代码如下:
#include<cstdio>
#include<cstring>
using namespace std;
int T,t,n,pre[1010],next[1010],val[1010][20],INF=1e9;
bool flag;
int gcd(int a,int b)
{
return b==0 ? a : gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
void Del(int pos)
{
int a=pre[pos],b=next[pos];
next[a]=b;
pre[b]=a;
}
int get_lcm()
{
int i,ret=1;
for(i=next[0];i<=n;i=next[i])
ret=lcm(ret,val[i][0]);
return ret;
}
bool solve(int p)
{
int i,j,k,minn=INF,pos;
bool flag2;
for(i=next[0];i<=n;i=next[i])
{
k=p%val[i][0];
if(k==0)
k=val[i][0];
k=val[i][k];
if(k<minn)
{
minn=k;pos=i;
flag2=true;
}
else if(k==minn)
flag2=false;
}
if(flag2)
{
Del(pos);
return true;
}
return false;
}
int main()
{
int i,j,k,num,ret,temp;
scanf("%d",&T);
for(t=1;t<=T;t++)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&val[i][0]);
for(j=1;j<=val[i][0];j++)
scanf("%d",&val[i][j]);
}
for(i=0;i<=n+1;i++)
{
pre[i]=i-1;
next[i]=i+1;
}
ret=0;
temp=0;
num=0;
while(true)
{
if(num==n)
break;
k=get_lcm();
flag=false;
for(i=1;i<=k;i++)
if(solve(ret+i))
{
flag=true;
break;
}
if(flag)
{
num++;
ret+=i;
}
else
break;
}
printf("%d %d\n",n-num,ret);
}
}