HDU6956 Pass! (BSGS数论)

题目链接
在这里插入图片描述
题目大意:
现在有N个人,传球,一开始球在1号手中,每秒都要传递一次球,现在告诉我们传球t秒后回到一号手中的方案数%mod的值为X,求解最小的时间t满足上述,若无解,输出-1 。

解题思路:
首先要推敲一下对于N,不同时间的时候的合法方案数的数量。
我是画了一个二叉树观察的。
显然t秒内传球方案数是(N-1)t 但是有不合法的方案数,因为最终必须回到一号。根据画的二叉树,手算发现规律如下。
t为奇数时 :
合法方案数sum=Σ(j=2;j<=t;j=j+2) (n-1)J - Σ(i=1;i<n;i=i+2) (n-1)i
t为偶数时:
合法方案数sum=Σ(j=1;j<=t;j=j+2) (n-1)J - Σ(i=2;i<n;i=i+2) (n-1)i
利用等比化简得到
sum=[(n-1)t + (-1)t (n-1) ] /n %mod=X%mod
那么不妨把分母约掉,常数移项。
等价于求解 (n-1)t = m的最小正整数t的解,BSGS算法即可
注意对于奇数的解ans必须也是奇数,同理偶数。
ps: 比赛的时候跑了800/2000 ms ((听说比赛的时候OJ跑的快些?
ps:填坑,比赛的代码(exBSGS)赛后TLE了。换成BSGS改成unmap就过了

#include<bits/stdc++.h>
#include <map>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <unordered_map>
#define ll long long
#define int ll
using namespace std ;
unordered_map<ll, int> H ;
int N, M,  P,ans ; // N ^x = M (mod P)
//const int P=998244353;
inline ll gcd(ll a, ll b)
{
    if (!b)
        return a ;
    return gcd(b, a % b) ;
}
inline ll expow(ll a, ll b, ll mod)
{
    ll res = 1 ;
    while (b)
        res = ((b & 1)?res * a % mod : res), a = a * a % mod, b >>= 1 ;
    return res ;
}
inline ll exgcd(ll &x, ll &y, ll a, ll b)
{
    if (!b)
    {
        x = 1, y = 0 ;
        return a ;
    }
    ll t = exgcd(y, x, b, a % b) ;
    y -= x * (a / b) ;
    return t ;
}
inline ll BSGS(ll a, ll b, ll mod, ll qaq)
{
    H.clear() ;
    ll Q, p = ceil(sqrt(mod)), x, y ;
    exgcd(x, y, qaq, mod), b = (b * x % mod + mod) % mod,
                           Q = expow(a, p, mod), exgcd(x, y, Q, mod), Q = (x % mod + mod) % mod ;
    for (ll i = 1, j = 0 ; j <= p ; ++ j, i = i * a % mod)
        if (!H.count(i))
            H[i] = j ;
    for (ll i = b, j = 0 ; j <= p ; ++ j, i = i * Q % mod)
        if (H[i])
            return j * p + H[i] ;
    return -1 ;
}
inline ll exBSGS()
{
    ll qaq = 1 ;
    ll k = 0, qwq = 1 ;
    if (M == 1)
        return 0 ;
    while ((qwq = gcd(N, P)) > 1)
    {
        if (M % qwq)
            return -1 ;
        ++ k, M /= qwq, P /= qwq, qaq = qaq * (N / qwq) % P ;
        if (qaq == M)
            return k ;
    }
    return (qwq = BSGS(N, M, P, qaq)) == -1 ? -1 : qwq + k ;
}
//N^x =m%p

signed main()
{
    ll t;
    scanf("%lld",&t);

    while(t--)
    {
        ll rnmgb=9999999999999999;
        P=998244353;
        ans=0;
        ll no=0;
        ll lcj;
        ll nm;
        scanf("%lld%lld",&N,&lcj);
        nm=N;
        ll   lcj1=((lcj*N)%P+(N-1)+P)%P;  // t奇数
        ll   lcj2=((lcj*N)%P-(N-1)+P)%P; // 偶数
        M=lcj1;
        N--;
        N %= P, M %= P, ans = exBSGS() ;
        if(ans<0||ans%2!=1)
        {
            no++;
        }
        else
        {
            rnmgb=min(rnmgb,ans);

        }
        P=998244353;
        ans=0;
        N=nm-1;
        M=lcj2;
        N %= P, M %= P, ans = exBSGS() ;
        if(ans<0||ans%2!=0)
        {
            no++;
        }
        else
        {

            rnmgb=min(rnmgb,ans);
        }
        if(no==2)
        {
            printf("-1\n");
            continue;
        }
        printf("%lld\n",rnmgb);

    }

}

BSGS 在这里插入图片描述
真想手写hash_map

#include<bits/stdc++.h>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#define LL long long
#define Re LL
using namespace std;
const int N=1e5+3;
int x,y,m,P;
unordered_map<LL,LL>B;
inline void in(Re &x)
{
    int f=0;
    x=0;
    char c=getchar();
    while(c<'0'||c>'9')
        f|=c=='-',c=getchar();
    while(c>='0'&&c<='9')
        x=(x<<1)+(x<<3)+(c^48),c=getchar();
    x=f?-x:x;
}
//x^k = y (mod P)
//k = am-b (m=sqrt(P)+1, a\in[1,m], b\in[0,m-1])
//(x^m)^a = y x^b (mod P)
inline int mi(Re x,Re k)
{
    Re s=1;
    while(k)
    {
        if(k&1)
            s=(LL)s*x%P;
        x=(LL)x*x%P,k>>=1;
    }
    return s%P;
}
int main()
{
    P=998244353;
    Re tt;
    in(tt);
    while(tt--)
    {
        Re lcj,rnm;
        in(lcj);
        in(rnm);
        Re lcj1=((lcj*rnm)%P+(lcj-1)+P)%P;  // t奇数
        Re lcj2=((lcj*rnm)%P-(lcj-1)+P)%P; // 偶数

        if(lcj2==1)
        {
            printf("0\n");
            continue;
        }

        x=lcj-1;
        y=lcj1;
        m=sqrt(P)+1;
        Re okk=0;
        Re daan=-1;
        for(Re b=0,s=y; b<m; ++b)
            B[s]=b,s=(LL)s*x%P;
        Re tmp=mi(x,m)%P;
        for(Re a=1,s=1; a<=m; ++a)
        {
            s=(LL)s*tmp%P;
            if(B.count(s)&&(a*m-B[s])%2==1)
            {
                if(daan==-1)
                {
                    daan=a*m-B[s];

                }

                okk++;
                break;
            }
        }

        B.clear();
        x=lcj-1;
        y=lcj2;
        m=sqrt(P)+1;
        //  Re okk=0;
        for(Re b=0,s=y; b<m; ++b)
            B[s]=b,s=(LL)s*x%P;
        tmp=mi(x,m)%P;
        for(Re a=1,s=1; a<=m; ++a)
        {
            s=(LL)s*tmp%P;
            if(B.count(s)&&(a*m-B[s])%2==0)
            {
                if(daan==-1)
                {
                    daan=a*m-B[s];
                }
                else
                    daan=min(daan,a*m-B[s]);
                okk++;
                break;
            }
        }
        B.clear();
        if(!okk)
            printf("-1\n");//continue;
        else
            printf("%lld\n",daan);

    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的校园二手书交易平台,源码+数据库+毕业论文+视频演示 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的校园二手书交易平台实现了图书信息查询。系统用到了关系型数据库中MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让校园二手书交易平台更能从理念走到现实,确确实实的让人们提升信息处理效率。 关键字:信息管理,时效性,安全性,MySql;Spring Boot
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值