Codeforces Round #822 (Div. 2) EF

Codeforces Round #822 (Div. 2) EF

E. Rectangular Congruence

题意

​ 给你一个长度为 n n n的数组 b b b,让你构造一个 n × n n\times n n×n的矩阵 a a a,使其满足 0 ≤ a i , j < n , 1 ≤ i , j , ≤ n 0\le a_{i,j}<n,1\le i,j,\le n 0ai,j<n,1i,j,n,且 a r 1 , c 1 + a r 2 , c 2 ≠ a r 1 , c 2 + a r 2 , c 1 ( m o d   n ) , 1 ≤ c 1 < c 2 ≤ n , 1 ≤ r 1 < r 2 ≤ n a_{r1,c1}+a_{r2,c2}\neq a_{r1,c2}+a_{r2,c1} (mod\ n),1\le c_1<c_2\le n,1\le r_1<r_2\le n ar1,c1+ar2,c2=ar1,c2+ar2,c1(mod n),1c1<c2n,1r1<r2n

思路

  • 推式子

让你求 a r 1 , c 1 + a r 2 , c 2 ≠ a r 1 , c 2 + a r 2 , c 1 ( m o d   n ) a_{r1,c1}+a_{r2,c2}\neq a_{r1,c2}+a_{r2,c1} (mod\ n) ar1,c1+ar2,c2=ar1,c2+ar2,c1(mod n),转换一下式子等价于求 a r 1 , c 1 − a r 1 , c 2 ≠ a r 2 , c 1 − a r 2 , c 2 ( m o d   n ) a_{r1,c1}-a_{r1,c2}\neq a_{r2,c1}-a_{r2,c2} (mod\ n) ar1,c1ar1,c2=ar2,c1ar2,c2(mod n),等价于同行任意两个位置的差,不能在其它行这两个位置差出来, 考虑做一个由于是 m o d    n \mod n modn 意义下的,因此考虑对于每一行构造一个 d d d唯一的等差数列即可,因此将第 i i i行的 d d d 构造为 i i i 直接输出就好

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 1e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
    e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
int a[1010][1010], b[1010];
int main() {
    ios::sync_with_stdio(false), cin.tie(0);    
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> b[i];
    
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= n; j ++) 
            cout << (i * (j - i + n) + b[i]) % n << " \n"[j == n];

    return 0;
}

F. Zeros and Ones

题意

给你一个长度为正无穷按照下面过程构造出的 0 / 1 0/1 0/1 S S S,构造如下:

一开始 S = ′ 0 ′ S='0' S=0,令 S ′ = S ⊕ ′ 111...11 1 ′ ( 即将 S 每一位取反 ) S'=S\oplus '111...111'(即将S每一位取反) S=S111...111(即将S每一位取反) ,然后令 S = S + S ′ (即将 S 和 S ′ 拼接起来) S=S+S'(即将S和S'拼接起来) S=S+S(即将SS拼接起来)

给你 n , m n,m n,m ,问你 ∑ i = 0 m − 1 S i ! = S n + i \displaystyle \sum_{i=0}^{m-1}S_i!=S_{n+i} i=0m1Si!=Sn+i

思路

  • d p dp dp

参考(68 封私信 / 80 条消息) Ander - 知乎 (zhihu.com)

​ 想办法快速求出 S i S_i Si的值,由于每次相当于 × 2 \times 2 ×2 再将取反的加到后面,也就是能有多少个 2 2 2的次幂就取了多少次反,因此 S i = S_i= Si=( i i i的二进制表示中 1 1 1出现的次数) % 2 \%2 %2

​ 设 f [ n ] [ m ] = ∑ i = 0 m − 1 [ S i ! = S n + i ] f[n][m]=\displaystyle \sum_{i=0}^{m-1}[S_i!=S_{n+i}] f[n][m]=i=0m1[Si!=Sn+i],考虑是否能从一些子状态推导出,对于边界 如果 m = 0 / 1 m=0/1 m=0/1 可以直接判断,如果 m % 2 = = 1 m\%2==1 m%2==1,我们可以直接求出最后面是否一样,将其转换成 m % 2 = = 0 m\%2==0 m%2==0的形式,因此对于 m % 2 = = 0 m\%2==0 m%2==0做如下讨论:

  • n % 2 = = 0 n\%2 ==0 n%2==0
    • 将奇偶分开有 S 2 k ! = S n + 2 k ⇔ S 2 k + 1 ! = S n + 2 k + 1 S_{2k}!=S_{n+2k}\Leftrightarrow S_{2k+1}!=S_{n+2k+1} S2k!=Sn+2kS2k+1!=Sn+2k+1(因为 2 k 2k 2k是偶数 n n n也是偶数,所以 2 k 2k 2k 2 k + 1 2k+1 2k+1只有 2 2 2进制最后一位不同,因此 S 2 k + 1 = S 2 k + 1 S_{2k+1}=S_{2k}+1 S2k+1=S2k+1,所以上式成立)
    • f [ n ] [ m ] = ∑ i = 0 m − 1 [ S i ! = S n + i ] f[n][m]=\displaystyle \sum_{i=0}^{m-1}[S_i!=S_{n+i}] f[n][m]=i=0m1[Si!=Sn+i]
    • f [ n ] [ m ] = 2 × ∑ k = 0 m / 2 − 1 [ S 2 k ! = S n + 2 k ] f[n][m]=\displaystyle 2\times \sum_{k=0}^{m/2-1}[S_{2k}!=S_{n+2k}] f[n][m]=2×k=0m/21[S2k!=Sn+2k]
    • f [ n ] [ m ] = 2 × ∑ k = 0 m / 2 − 1 [ S 2 k ! = S n + 2 k ] f[n][m]=\displaystyle 2\times \sum_{k=0}^{m/2-1}[S_{2k}!=S_{n+2k}] f[n][m]=2×k=0m/21[S2k!=Sn+2k] (考虑式子的意义,由于下标都是偶数,因此下标右移一位, S S S的值不会变)
    • f [ n ] [ m ] = 2 × ∑ k = 0 m / 2 − 1 [ S k ! = S n / 2 + k ] f[n][m]=\displaystyle 2\times \sum_{k=0}^{m/2-1}[S_{k}!=S_{n/2+k}] f[n][m]=2×k=0m/21[Sk!=Sn/2+k]
    • f [ n ] [ m ] = 2 × f [ n / 2 ] [ m / 2 ] f[n][m]=\displaystyle 2\times f[n/2][m/2] f[n][m]=2×f[n/2][m/2]
  • n % 2 = = 1 n\%2==1 n%2==1
    • 和上面偶数的一样考虑性质 S 2 k ! = S n + 2 k ⇔ S 2 k = S n + 2 k − 1 S_{2k}!=S_{n+2k}\Leftrightarrow S_{2k}=S_{n+2k-1} S2k!=Sn+2kS2k=Sn+2k1 n n n是奇数最后一位是 1 1 1,因此去掉最后一位的贡献就相等了), S 2 k + 1 ! = S n + 2 k + 1 ⇔ S 2 k = S n + 2 k + 1 S_{2k+1}!=S_{n+2k+1}\Leftrightarrow S_{2k}=S_{n+2k+1} S2k+1!=Sn+2k+1S2k=Sn+2k+1
    • f [ n ] [ m ] = ∑ i = 0 m − 1 [ S i ! = S n + i ] f[n][m]=\displaystyle \sum_{i=0}^{m-1}[S_i!=S_{n+i}] f[n][m]=i=0m1[Si!=Sn+i]
    • f [ n ] [ m ] = ∑ k = 0 m / 2 − 1 [ S 2 k ! = S n + 2 k ] + [ S 2 k + 1 ! = S n + 2 k + 1 ] f[n][m]=\displaystyle \sum_{k=0}^{m/2-1}[S_{2k}!=S_{n+2k}]+[S_{2k+1}!=S_{n+2k+1}] f[n][m]=k=0m/21[S2k!=Sn+2k]+[S2k+1!=Sn+2k+1]
    • f [ n ] [ m ] = ∑ k = 0 m / 2 − 1 [ S 2 k = = S n + 2 k − 1 ] + [ S 2 k = = S n + 2 k + 1 ] f[n][m]=\displaystyle \sum_{k=0}^{m/2-1}[S_{2k}==S_{n+2k-1}]+[S_{2k}==S_{n+2k+1}] f[n][m]=k=0m/21[S2k==Sn+2k1]+[S2k==Sn+2k+1](考虑式子的意义,右移不变)
    • f [ n ] [ m ] = ∑ k = 0 m / 2 − 1 [ S k = = S ( n − 1 ) / 2 + k ] + [ S k = = S ( n + 1 ) / 2 + k ] f[n][m]=\displaystyle \sum_{k=0}^{m/2-1}[S_{k}==S_{(n-1)/2+k}]+[S_{k}==S_{(n+1)/2+k}] f[n][m]=k=0m/21[Sk==S(n1)/2+k]+[Sk==S(n+1)/2+k] (容斥一下)
    • f [ n ] [ m ] = m − ∑ k = 0 m / 2 − 1 [ S k ! = S ( n − 1 ) / 2 + k ] + [ S k ! = S ( n + 1 ) / 2 + k ] f[n][m]=\displaystyle m-\sum_{k=0}^{m/2-1}[S_{k}!=S_{(n-1)/2+k}]+[S_{k}!=S_{(n+1)/2+k}] f[n][m]=mk=0m/21[Sk!=S(n1)/2+k]+[Sk!=S(n+1)/2+k]
    • f [ n ] [ m ] = m − f [ ( n − 1 ) / 2 ] [ m / 2 ] − f [ ( n + 1 ) / 2 ] [ m / 2 ] f[n][m]=\displaystyle m-f[(n-1)/2][m/2]-f[(n+1)/2][m/2] f[n][m]=mf[(n1)/2][m/2]f[(n+1)/2][m/2]

对于每个 f [ n ] [ m ] f[n][m] f[n][m] 用它的子状态求出,记忆化一下即可,即复杂度为 O ( l o g n l o g m ) O(lognlogm) O(lognlogm)

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 1e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
    e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
LL n, m, k;
int a[N];
map<pair<LL, LL>, LL> f;
int g(LL x) {
    int t = 0;
    for (int i = 0; i < 64; i ++)
        if (x >> i & 1) t ^= 1;
    return t;    
}
LL dfs(LL n, LL m) {
    if (!m) return 0;
    if (m == 1) return g(n);
    if (f.find({n, m}) != f.end()) return f[{n, m}];
    if (m & 1) return f[{n, m}] = dfs(n, m - 1) + (g(m - 1) != g(n + m - 1));
    if (n % 2 == 0) return f[{n, m}] = 2ll * dfs(n / 2, m / 2);
    return f[{n, m}] = m - dfs((n - 1) / 2, m / 2) - dfs((n + 1)/ 2, m / 2);
}
int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    int T;
    cin >> T;
    while (T -- ) {
        cin >> n >> m;
        cout << dfs(n, m) << '\n';
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值