voiddfs( int cur, int sum, int k, int lst ){ if( cur == 0 ) { mex.insert( sum ); return; } for( int i = lst; i <= cur && i < k; ++ i ) { dfs( cur - i, sum * f[i], k, i ); } }
voidinit2( ){ f[1] = 1; for( int i = 2; i <= 23; ++ i ) { mex.clear( ); mex.insert( 0 ); dfs( i, 1, i, 1 ); f[i] = 0; // mex while( mex.count( f[i] ) ) ++ f[i]; } }
int pri[maxn], pcnt; bool isp[maxn]; int g[maxn];
voidinit( ll N ){ pcnt = 0; fill( isp + 2, isp + N + 1, 1 ); for( ll i = 2; i <= N; ++ i ) { if( isp[i] ) pri[++ pcnt] = i, g[i] = 1; for( ll j = 1; j <= pcnt && i * pri[j] <= N; ++ j ) { ll p = pri[j]; isp[i * p] = 0; g[i * p] = g[i] + 1; if( i % p == 0 ) break; } } }
voidsolve( ){ int n = read( ); ll c = read( ); init( n + 1 ); init2( ); g[1] = 1;
ll res = 0; ll ci = 1; for( int i = 1; i <= n; ++ i ) { ci = ( ci * c ) % mod; res = ( res + f[g[i]] * ci ) % mod; // cout << i << ' ' << g[i] << '\n'; } cout << res << '\n'; }
for( int i = 1; i <= n; ++ i ) { for( int j = 1; j <= m; ++ j ) { a[i][j] = val - a[i][j]; if( a[i][j] < 0 ) return0; } } if( a[1][1] != all || a[n][m] != all ) return0;
for( int k = 2; k < n + m; ++ k ) { ll down = 0; // 下 for( int i = 1; i <= n; ++ i ) { int j1 = k - i, j2 = k + 1 - i; ll cur = valid( j1 ) ? a[i][j1] : 0; ll nxt = valid( j2 ) ? a[i][j2] : 0;
ll right = nxt - down; if( right < 0 || right > cur ) return0; // 流量不够 或者 超了 down = cur - right; // 剩余只能向下流 } if( down != 0 ) return0; // 流量不刚好 } return1; }
voidfail( ){ cout << -1 << '\n'; }
voidsolve( ){ n = read( ), m = read( ); for( int i = 1; i <= n; ++ i ) { for( int j = 1; j <= m; ++ j ) { a[i][j] = read( ); } }
if( a[1][1] != a[n][m] ) returnfail( );
if( n == 1 ) { bool ok = 1; for( int j = 1; j <= m; ++ j ) { if( a[1][j] != a[1][1] ) ok = 0; } if( !ok ) returnfail( ); else cout << 0 << '\n'; return ; }
if( m == 1 ) { bool ok = 1; for( int i = 1; i <= n; ++ i ) { if( a[i][1] != a[1][1] ) ok = 0; } if( !ok ) returnfail( ); else cout << 0 << '\n'; return ; }
ll all = a[1][2] + a[2][1] - 2 * a[1][1];
if( all < 0 ) returnfail( );
if( check( all ) ) cout << all << '\n'; elsefail( ); }
voidsolve( ){ int n = read( ); if( n & 1 || n == 2 ) { cout << -1 << '\n'; return ; }
vector<int> a, b(n), c(n); int k = n / 2;
if( k % 3 != 1 ) { for( int x = 0; x < k; ++ x ) { a.push_back( x ); a.push_back( x + k ); } } else { int h = (k - 1) / 3; a.push_back( 2 * h ); a.push_back( h ); a.push_back( 0 ); a.push_back( 2 * h + k ); a.push_back( h + k ); a.push_back( k );
for( int x = 1; x < k; ++ x ) { if( x == h || x == 2 * h ) continue; a.push_back( x ); a.push_back( x + k ); } }
for( int i = 0; i < n; ++ i ) { c[i] = n - 1 - a[i]; b[i] = c[i] - a[i]; if( i + 1 < n && a[i + 1] >= k ) b[i] -= 1; if( a[i] >= k ) b[i] += n; }
for( int x : a ) cout << x << ' '; cout << '\n';
for( int x : b ) cout << x << ' '; cout << '\n';
for( int x : c ) cout << x << ' '; cout << '\n'; }
官方题解给出了另一种思路。首先通过求和发现恰好有 B/2 次进位,假设 P 是一个排列,如果想要 Q 是一个排列,最简单的方式就是让它成为 P 的循环平移,即 qp=(p−t)modB。
这样问题似乎就变成了选择一个合适的偏移量 t,但在考虑 t 之前,我们还需要保证得到的 R 是一个排列。
设这一列收到的进位是 cp∈{0,1},那么 rp≡p+qp+cp≡2p−t+cp(modB)。令 B=2n,由于2(p+n)≡2p(modB),所以 p 与 p+n 在 2pmodB 意义下会得到相同的结果,仅靠一个常数 t 无法让 R 成为完整的排列。
但正好 cp∈{0,1},可以用它来区分这一对相同的结果。自然地,我们会想到把 p 和 p+n 配对,并令这一对的进位互补:cp+n=1−ap,那么这一对生成的两个结果 rp,rp+n 就是两个相邻的数 2p−t,2p−t+1(modB)。