标签:分享 color 题意 const nbsp bug 个数 can 无法
题意:
给定一长度为 n 的整数序列 $a$,将其复制m次,并接成一条链,每相邻K个相同的整数会消除,然后其他的整数继续结成一条链,直到不能消除为止,求问最终剩余多少个整数。
解法:
首先将长度为n的序列消干净,然后接下来的消除操作必然是在两个序列相交处进行消除,对于接在中间的序列,原消法等价于序列的左侧和右侧不停消除直到无法继续。
分类讨论:
1.序列左右消干净了,这样答案为0
2.序列消得剩下一种元素,统计该元素的总个数,如果K|sum,则为0,不然为sum%K个加上左右侧剩余元素。
3.序列剩下一段元素:
考虑计算消除了多少个:
(1)首先剩余的元素拼在一起 如果有%K!=0的相同元素接在一起 将会消成sum%K
(2)其次中间序列左右消除的个数。
这样就解决了,效率$O(n)$
const int N = 100010; int n,K,m,tot,a0[N],a[N],b[N]; int main() { cin >> n >> K >> m; int cnt = n; FOR(i,1,n) scanf("%d", &a0[i]); b[0] = -1; FOR(i, 1, n) { if(a0[i] == b[tot]) a[tot]++; else { if(tot) { cnt -= a[tot]-a[tot]%K; a[tot] %= K; if(a[tot]==0) tot--; } if(!tot || a0[i] != b[tot]) a[++tot] = 1, b[tot] = a0[i]; else a[tot]++; } } cnt -= a[tot]-a[tot]%K; a[tot] %= K; if(a[tot]==0) tot--; if(!tot) { cout << 0 << endl; return 0; } // FOR(i,1,tot) cout<<a[i]<<‘-‘<<b[i]<<endl; int l=1, r=tot; while(l<r) { if(b[l]!=b[r] || (a[l]+a[r])%K) break; l++,r--; } // debug(l); // debug(r); // debug(cnt); if(l>r) { cout << 0 << endl; return 0; } else if(l==r) { if(1ll*a[l]*m%K==0) cout << 0 << endl; else cout << cnt-a[l]+1ll*a[l]*m%K << endl; } else { LL ans = 1ll*m*cnt,tmp = cnt; FOR(i,l,r) tmp -= a[i]; ans -= 1ll*(m-1)*tmp; if(b[l]==b[r]) ans -= 1ll*(m-1)*((a[r]+a[l]) - (a[r]+a[l])%K); cout << ans << endl; } return 0; }
标签:分享 color 题意 const nbsp bug 个数 can 无法
原文地址:http://www.cnblogs.com/lawyer/p/7742655.html