题意:挺好懂得
分析:先计算出如果不能用(减2)操作,至少需要多少个(减3)操作,这个很好计算
然后就是尽量多的去减少(减3)操作,肯定先抹平 余2 和 余1 的,然后就可以了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <iostream> #include <ctime> #include <vector> #include <cmath> #include <map> #include <queue> #include <algorithm> #include <cstring> using namespace std; typedef long long LL; const int N=1e5+5; const int INF=0x3f3f3f3f; const int mod=1e9+7; int f[N],a[N],d[6]; int main() { int n,m; while(~scanf("%d%d",&n,&m)){ memset(d,0,sizeof(d)); int sum=0,c=0; for(int i=1;i<=n;++i){ scanf("%d",&a[i]); ++d[a[i]%6]; sum+=a[i]/6; if(a[i]%6==1){ if(a[i]>6)++c; } } int ret=0; for(int i=0;i<=m;++i){ int ans; if(i<=d[1]+d[2]+d[4]+d[5]){ ans=d[1]+d[2]+d[4]+d[5]-i+d[4]+d[5]+d[3]+sum*2; } else { int k[6]; for(int j=1;j<=5;++j)k[j]=d[j]; k[2]=k[4];k[4]=0; k[3]+=k[5];k[5]=0; k[1]=0; int tmp=sum-c; k[2]+=c;k[3]+=c; int t=i-d[1]-d[2]-d[4]-d[5]; if(t<=k[2]){ k[2]-=t; ans=tmp*2+k[2]+k[3]; } else { t-=k[2];k[2]=0; int p=t/3; if(tmp<=p){ p-=tmp; tmp=0; } else tmp-=p,p=0; t=t%3+p*3; t/=2; ans=max(0,tmp*2+k[3]-t); } } ret=(ret+ans)%mod; } printf("%d ",ret); } return 0; }