uva 10273 - Eat or Not to Eat?
题意:农场有n头奶牛,每头奶牛都有一个产奶周期ti天(ti<=10),每天产奶ai,每天农场都想杀一头奶牛吃,但希望杀产奶最小的一头,如果有多头产奶最小,则那天将不杀。现问最后剩下几头,杀最后一头牛是第几天。
思路:n头牛产奶周期的最小公倍数G一定小于10!,可以按产奶的周期把奶牛分成10类。然后枚举天数,找出这10类中的最小值和最小值有多少个。(枚举天数的时候,只要在G周期内没有杀牛,就一定不会杀了)

#include<stdio.h> #include<string.h> #include<vector> #include<set> #include<map> #include<algorithm> using namespace std; set<int>as[12][11][255]; map<int,int>bs[12][11]; vector<int>cs[1005]; int gcd(int x,int y){return y?gcd(y,x%y):x;} int main() { int i,j,k,t,n,m,ans1,ans2,idx,g; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i = 1; i <= 11; ++ i) for(j = 0; j < 11; ++ j) for(k = 0; k < 255; ++ k) as[i][j][k].clear(); for(i = 1; i <= 11; ++ i) for(j = 0; j < 11; ++ j) bs[i][j].clear(); for(i = 1; i <= n; ++ i) cs[i].clear(); g = 1; for(i = 1; i <= n; ++ i){ scanf("%d",&m); if(m)g = g / gcd(g,m) * m; for(j = 0; j < m; ++ j){ scanf("%d",&k); as[m][j][k].insert(i); bs[m][j][k]++; cs[i].push_back(k); } } ans1=n; ans2=0; int ii; i = 1; for(ii = 1; ii <= g; ++ ii,++i){ k = 300; m = 0; for(j = 1; j <= 10; ++ j){ if(bs[j][(i-1)%j].size()==0)continue; int ts = bs[j][(i-1)%j].begin()->first; if(k>ts){ m = as[j][(i-1)%j][ts].size(); k = ts; idx = *(as[j][(i-1)%j][ts].begin()); }else if(k==ts)m += as[j][(i-1)%j][ts].size(); } if(k==300||m^1)continue; ii = 0; ans1--; ans2 = i; k = cs[idx].size(); for(j = 0; j < k; ++ j){ int v = cs[idx][j]; as[k][j][v].erase(idx); bs[k][j][v]--; if(bs[k][j][v]==0)bs[k][j].erase(v); } } printf("%d %d\n",ans1,ans2); } return 0; }