赛场上我的推导就止步于此了,下面展开赛后的细节:令 S(A)=i=0∑n−12iai,假设 at=x,我们现在需要把 x 从 t 移动到 k,于是令 d=(t−k+n)(modn),并构造 ai′=ai+d(modn),显然 ak′=at=x,对于原来位于 j 的元素 aj,循环左移 d 位后,它的新位置 i 满足 i≡j−d(modn),代入原式可以得到:
#include<bits/stdc++.h> usingnamespace std; using ll = longlong; using ull = unsignedlonglong; using i128 = __int128_t; using pii = pair<int, int>; using pll = pair<ll, ll>;
intgetid( string s ){ int rank = ranks[s[0]]; int suit = suits[s[1]]; return suit * 13 + rank - 2; }
bool vis[55];
structHand { int type; int val[5]; };
/* 0:Highcard 1:Pair 2:Two pairs 3:Three of a kind 4:Straight 5:Flush 6:Full house 7:Four of a kind 8:Straight flush */
Hand calc( vector<int> a ){ int cnt[15] = { }; int suitcnt[4] = { }; for( int id : a ) { int rank = id % 13 + 2; int suit = id / 13; cnt[rank] ++; suitcnt[suit] ++; } bool flush = 0; for( int i = 0; i < 4; ++ i ) { if( suitcnt[i] == 5 ) flush = 1; }
int straight = 0; vector<int> dif; for( int i = 2; i <= 14; ++ i ) { if( cnt[i] ) dif.push_back( i ); }
if( dif.size( ) == 5 ) { bool ok = 1; for( int i = 1; i < 5; ++ i ) { if( dif[i] != dif[i-1] + 1 ) ok = 0; } if( ok ) straight = dif.back( ); if( dif[0] == 2 && dif[1] == 3 && dif[2] == 4 && dif[3] == 5 && dif[4] == 14 ) straight = 5; }
// 同花 if( flush ) { Hand res = { 5, { } }; int pos = 0; for( int i = 14; i >= 2; -- i ) { for( int j = 0; j < cnt[i]; ++ j ) { res.val[pos ++] = i; } } return res; }
// 顺子 if( straight ) return { 4, { straight } };
// 三条 if( three ) { Hand res = { 3, { } }; res.val[0] = three; int pos = 1; for( int i = 14; i >= 2; -- i ) { if( cnt[i] == 1 ) res.val[pos ++] = i; } return res; }
// 两对 if( pair.size( ) == 2 ) { int single = 0; for( int i = 14; i >= 2; -- i ) { if( cnt[i] == 1 ) single = i; } return { 2, { pair[0], pair[1], single } }; }
// 一对 if( pair.size( ) == 1 ) { Hand res = { 1, { } }; res.val[0] = pair[0]; int pos = 1; for( int i = 14; i >= 2; -- i ) { if( cnt[i] == 1 ) res.val[pos ++] = i; } return res; }
// 高牌 Hand res = { 0, { } }; int pos = 0; for( int i = 14; i >= 2; -- i ) { if( cnt[i] == 1 ) res.val[pos ++] = i; } return res; }
intcheck( const Hand &a, const Hand &b ){ if( a.type != b.type ) return a.type > b.type ? 1 : -1; for( int i = 0; i < 5; ++ i ) { if( a.val[i] != b.val[i] ) return a.val[i] > b.val[i] ? 1 : -1; } return0; }
voidsolve( ){ memset( vis, 0, sizeof vis ); string s; vector<int> c, p; for( int i = 0; i < 4; ++ i ) { cin >> s; int id = getid( s ); vis[id] = 1; c.push_back( id ); } for( int i = 0; i < 4; ++ i ) { cin >> s; int id = getid( s ); vis[id] = 1; p.push_back( id ); }
vector<int> rem; for( int i = 0; i < 52; ++ i ) { if( !vis[i] ) rem.push_back( i ); }
Hand handc[52]; Hand handp[52];
for( int x : rem ) { vector<int> nc = c; vector<int> np = p; nc.push_back( x ); np.push_back( x ); handc[x] = calc( nc ); handp[x] = calc( np ); }
// 法国赢: 存在一个 x, 使得所有 y 都能获胜 // 我赢:所有 x,都存在一个 y 能获胜
int cnt = 0; // 我赢的次数 int all = rem.size( ); for( int x : rem ) { int winc = 0, winp = 0, draw = 0; // x 我,y 法国,z 平局, for( int y : rem ) { if( x == y ) continue; int res = check( handc[y], handp[x] ); if( res == 1 ) winc ++; if( res == 0 ) draw ++; if( res == -1 ) winp ++; }
ll ask( int l, int r ){ if( l > r ) return0; ll res = sum2[r]; if( l ) res -= sum2[l - 1]; if( res < 0 ) res += mod; return res; }
voidsolve( ){ int n = read( ), q = read( ); string s; cin >> s; for( int i = 1; i <= n; ++ i ) { a[i] = read( ); sum1[i] = sum1[i-1] + a[i]; }
premin[0] = sum1[0]; for( int i = 1; i <= n; ++ i ) { premin[i] = min( premin[i-1], sum1[i] ); }
sufmax[n] = sum1[n]; for( int i = n - 1; i >= 0; -- i ) { sufmax[i] = max( sufmax[i+1], sum1[i] ); }
for( int i = 1; i <= n; ++ i ) { sum2[i] = ( sum2[i-1] + sum1[i] ) % mod; if( sum2[i] < 0 ) sum2[i] += mod; }
acam.init( ); for( int i = 1; i <= q; ++ i ) { string t; cin >> t; acam.insert( t, i ); } acam.build( );
int u = 0; for( int i = 0; i < n; ++ i ) { u = acam.nxt[u][s[i] - 'a']; for( int v = u; v; v = acam.up[v] ) { if( acam.len[v] ) pos[v].push_back( i - acam.len[v] + 1 ); } }
for( int i = 1; i <= q; ++ i ) { int u = acam.ed[i]; if( vis[u] ) { cout << ansmax[u] << " " << anssum[u] << '\n'; continue; } int m = acam.len[u]; ll mx = -inf; for( int p : pos[u] ) { mx = max( mx, sufmax[p + m] - premin[p] ); }
ll sum = 0; int lst = -1; for( int p : pos[u] ) { ll cntl = p - lst; ll cntr = n - p - m + 1; ll sumr = ask( p + m, n ); ll suml = ask( lst + 1, p ); sum = ( sum + cntl % mod * sumr % mod ) % mod; sum = ( sum - cntr % mod * suml % mod + mod ) % mod; lst = p; } vis[u] = 1; ansmax[u] = mx; anssum[u] = sum; cout << mx << " " << sum << '\n'; }