[codeforces1184A2]Heidi Learns Hashing (Medium)

题目要求找到满足存在x,使得x与x右移k位异或等于给定的y的所有k值。提供了一个长度为n的01串y,需要计算符合条件的k的数量。通过分析,可以发现解与n和u的最大公约数有关,最终可以通过预处理gcd信息并枚举k来求解问题。
摘要由CSDN通过智能技术生成

time limit per test : 2 seconds
memory limit per test : 256 megabytes

分数:2100 // 虽然我觉得思维难度还挺高的,像是2500的题,不像普通的2100那么简单

After learning about polynomial hashing, Heidi decided to learn about shift-xor hashing. In particular, she came across this interesting problem.

Given a bitstring y ∈ { 0 , 1 } n y∈ \{0,1\} ^n y{0,1}n find out the number of different k ( 0 ≤ k &lt; n ) k (0≤k&lt;n) k(0k<n) such that there exists x ∈ { 0 , 1 } n x∈\{0,1\}^n x{0,1}n for which y = x ⊕ s h i f t k ( x ) y=x⊕shift^k(x) y=xshiftk(x).

In the above, ⊕ is the xor operation and shiftk is the operation of shifting a bitstring cyclically to the right k times. For example, 001⊕111=110 and shift3(00010010111000)=00000010010111.

Input

The first line contains an integer n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 ) n (1≤n≤2⋅10^5) n(1n2105), the length of the bitstring y y y.
The second line contains the bitstring y y y.

Output

Output a single integer: the number of suitable values of k k k.

Example
Input

4
1010

Output

3

Note

In the first example:

1100⊕shift1(1100)=1010
1000⊕shift2(1000)=1010
0110⊕shift3(0110)=1010

There is no x x x such that x⊕x=1010, hence the answer is 3.

题意:
给一个长度为n的01串 y y y,问有多少个 k ( 0 &lt; = k &lt; n ) k(0&lt;=k&lt;n) k(0<=k<n)满足存在一个长度为n的01串x使得 x ⊕ s h i f t k ( x ) = y x⊕shift^k(x) = y xshiftk(x)=y
s h i f t k ( x ) shift^k(x) shiftk(x)操作是将字符串x向右循环位移 k k k位。

题解:
考虑位移k的情况
显然字符串满足以下等式

x[1]^x[1+k]=y[1]
x[2]^x[2+k]=y[2]
...
x[n]^x[k]=y[n]

将等式拆分:

//对于所有i<=k都满足如下情况
x[i]^x[i+k]=y[i]
x[i+k]^x[i+2*k]=y[i+k]
...

可以发现对于所有的 g c d ( n , u ) = k gcd(n,u) = k gcd(n,u)=k的情况,都符合上面的方程组
将方程组化简可得:

y[i]^y[i+k]^y[i+2*k]^.... = x[i]^x[i+k]^x[i+k]^.....(相邻两两相消) = 0

那么我们可以预处理出所有 g c d ( n , i ) gcd(n,i) gcd(n,i)是否能够成为解,最后直接枚举 k k k统计答案即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=200004;
int ok[MAXN],l;
char s[MAXN];
void work(int base){
    for(int i=1;i<=base;i++){
        ll sum=0;
        for(int j=i;j<=l;j+=base){
            sum^=(s[j]-'0');
        }
        if(sum)return ;
    }
    ok[base]=1;
}
int main(){
    scanf("%d",&l);
    scanf("%s",s+1);
    memset(ok,0,sizeof(ok));
    bool flag=0;
    for(int i=1;i<=l;i++){
        if(s[i]=='1')flag=1;
    }
    if(!flag)ok[0]=1;
    for(int k=1;k*k<=l;k++){
        if(l%k==0){
            work(k);
            work(l/k);
        }
    }
    int ans=0;
    if(!flag)ans++;
    for(int k=1;k<l;k++){
        ans+=ok[__gcd(l,k)];
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值