“21 天好习惯”第一期-3

Korney Korneevich and XOR (F1&F2)

求递增子序列所有不同的异或值

显然,对于递增子序列 x < y < z , a x   X O R   a y   X O R   a z = A x<y<z,a_x\ XOR\ a_y\ XOR\ a_z = A x<y<z,ax XOR ay XOR az=A,如果有 d > z , a d > a z d>z,a_d>a_z d>z,ad>az,那么可以得到 A   X O R   d A\ XOR\ d A XOR d

于是有两种方法来通过动态规划转移:

方法一:

按序列的下标从小到大开始转移,对于当前序列的下标 i i i,一定是目前最大的, d p [ x ] dp[x] dp[x]存前面的递增子序列异或得到 x x x时递增子序列最后一个数的最小值,只要那么只要满足 a [ i ] > d p [ x ] a[i]>dp[x] a[i]>dp[x]就可以得到 ( a [ i ]   X O R   x ) (a[i]\ XOR\ x) (a[i] XOR x)

code

在这里插入图片描述

方法二:

按序列的值从小到大开始转移,对于当前序列的值 i i i,一定是目前最大的, d p [ x ] dp[x] dp[x]存前面的递增子序列异或得到 x x x时递增子序列最后一个数下标的最小值,只要那么只要找到最小的 p o s , ( p o s > d p [ x ] & & a p o s = = i ) pos,(pos>dp[x]\&\&a_{pos}==i) pos,(pos>dp[x]&&apos==i)就可以得到 ( i   X O R   x ) (i\ XOR\ x) (i XOR x)

code

在这里插入图片描述

261. Discrete Roots

求出 x k ≡ a ( m o d p ) , x ∈ 0 ∼ ( p − 1 ) {{x^k\equiv a\pmod p},x\in{0\sim (p-1)}} xka(modp)x0(p1)的所有解。

找到一个特解

因为 p {p} p是质数,所以可以求出 p {p} p的质数 g {g} g。因此对于模 p {p} p意义下的任意数 x ( 0 ≤ x < p ) {x(0\le x< p)} x(0x<p)有且仅有一个数 i ( 0 ≤ x < p − 1 ) {i(0\le x< p-1)} i(0x<p1)满足 x = g i {x=g^i} x=gi

假设 x = g c {x=g^c} x=gc,则 ( g c ) k ≡ a ( m o d p ) {(g^{c})^k\equiv a\pmod p} (gc)ka(modp),稍加变换,有:

( g k ) c ≡ a ( m o d p ) {(g^k)^c\equiv a\pmod p } (gk)ca(modp)

然后套用 B S G S {BSGS} BSGS就一定能求出 c {c} c,然后得到原方程的一个特解 x 0 = g c ( m o d p ) ) {x_0=g^c\pmod p)} x0=gc(modp))

找到所有解

g k c ≡ a ( m o d p ) {g^{kc}\equiv a\pmod p} gkca(modp)

⇐ g k c + t ϕ ( p ) ≡ a ( m o d p ) {\Leftarrow g^{kc+t\phi(p)}\equiv a\pmod p} gkc+tϕ(p)a(modp)

则, ∀ t ∈ Z , k ∣ t ϕ ( p ) , x = t ϕ ( p ) k {\forall t \in \mathbb{Z},k|t\phi(p),x=\frac{t\phi(p)}{k}} tZ,ktϕ(p),x=ktϕ(p)

对上面的式子,显然有 k gcd ⁡ ( k , ϕ ( p ) ) ∣ t {\frac{k}{\gcd(k,\phi(p))}\mid t} gcd(k,ϕ(p))kt,设 t = k gcd ⁡ ( k , ϕ ( p ) ) ∗ i {t=\frac{k}{\gcd(k,\phi(p))}*i} t=gcd(k,ϕ(p))ki,则有

x = g c + ϕ ( p ) gcd ⁡ ( k , ϕ ( p ) ) ∗ i {x=g^{c+\frac{\phi(p)}{\gcd(k,\phi(p))}*i}} x=gc+gcd(k,ϕ(p))ϕ(p)i

code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=(1<<16)-1;
int gcd(int a,int b) {
    if(!b) return a;
    while((a%=b) && (b%=a));
    return a+b;
}
int qpow(ll a,ll b,int mod) {
    ll res=1;
    while(b) {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
int generator(int p) {
    vector<int> fact;
    int phi = p - 1, n = phi;
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            fact.push_back(i);
            while (n % i == 0) n /= i;
        }
    }
    if (n > 1) fact.push_back(n);
    for (int res = 2; res <= p; ++res) {
        bool ok = true;
        for (int factor : fact) {
            if (qpow(res, phi / factor, p) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return res;
    }
    return -1;
}
struct HASH{
    int v[maxn+1],tot,ed=0;
    struct node{
        int t,p,next;
    }a[maxn<<1];
    void ins(int x,int y) {
        int k=x&maxn;
        if(v[k]!=ed) {
            v[k]=ed;
            a[k].t=x,a[k].p=y,a[k].next=0;
        }
        else {
            for(;;k=a[k].next) {
                if(a[k].t==x) return a[k].p=y,void();
                if(!a[k].next) break;
            }
            a[k].next=++tot,a[tot].t=x,a[tot].p=y,a[tot].next=0;
        }
    }
    int find(int x) {
        int k=x&maxn;
        if(v[k]!=ed) return -1;
        for(;;k=a[k].next)
            if(a[k].t==x) return a[k].p;
            else if(!a[k].next) return -1;
    }
}mp;
int bsgs(int g,int b,int p,int k) {
    if(b==1) return 0;
    int m=ceil(sqrt(p));
    mp.tot=maxn;
    ll tmp=1,s=1,x=qpow(g,k%(p-1),p);
    for(int j=0; j<m; ++j)
        mp.ins(tmp*b%p,j),tmp=tmp*x%p;
    for(int i=1; i<=m; ++i) {
        s=s*tmp%p;
        if(~mp.find(s)) return i*m-mp.find(s);
    }
    return -1;
}
signed main() {
    cin.sync_with_stdio(false), cin.tie(nullptr),cout.tie(nullptr);
    int p,k,a;
    cin>>p>>k>>a; mp.ed=1;
    if(a==0) return cout<<"1\n0\n",0;
    int g=generator(p);
    int res=bsgs(g,a,p,k);
    if(res==-1) return cout<<"0\n",0;
    int delta=(p-1)/gcd(k,p-1),tmp=qpow(g,delta,p);
    vector<int>ans;
    ans.emplace_back(qpow(g,res,p));
    for(res+=delta;res<p-1;res+=delta) 
        ans.emplace_back(1LL*ans.back()*tmp%p);
    sort(ans.begin(), ans.end());
    cout<<ans.size()<<'\n';
    for(int i:ans) cout<<i<<' ';
    return 0;
}

v e c t o r {vector} vector代替 H A S H {HASH} HASHcode

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值