• K


    Time Limit : 1 Second      Memory Limit : 65536 KB

    Source : 第十届山东省ACM省赛

    Problem Link : ZOJ 4123

    Author : Houge  Date : 2019-5-24

      看了快一周的k题,看了好多题解,还是不明白,只恨自己不是数论大佬。昨天看了本校数竞大佬Ch_3225的题解,感觉还不错,和我目前看过的都不太一样(但还是看不懂)。征得同意后,这里就直接copy上来了。

    (注意:在此篇题解中,为码字方便,记a^b为a的b次方,而不是c语言定义的异或运算。优先级以幂的运算优先级为准。)

    (“|”符号为整除符号,即右边的数➗左边的数得到整数)

    题目

      即求x∈{1,2,.....,2^p}使得a^x≡x^a(mod 2^p)。

    分析:

      要求式为了找到x的个数,我们考虑什么样的x满足上述方程。

      ·变形,原式即为2^p|abs(a^x-x^a)。  (①式)

      ·记abs(a^x-x^a)为R。

    我们考虑a^x-x^a的2的幂次。为了从右式通过提取因子提出尽可能多的2,我们设:

      ·a=a0*2^i;

      ·x=x0*2^j;

    其中a0和x0都是奇数。

    于是代入①式,2^p|abs((a0*2^i)^(x0*2^j)-(x0*2^j)^(a0*2^i))

    于是    R=2^(min((i*x0*2^j),(j*a0*2^i)))*p;(x!=a)(p是某个奇数)

    或    R=0;(x==a)

    即    R=2^(min((i*x),(j*a)))*p;(x!=a)(p是某个奇数)

    或    R=0;(x==a)

    当x!=a的时候,我们想要使x满足该方程,需要

        2^p|2^(min((i*x),(j*a)))*p;(p是某个奇数)

    即  p<=min(i*x,j*a)

    即  i*x>=p且j*a>=p  ②式

    因为我们要找的是合法的x,并且我们设的j也和x有关,于是我们将上式变形:

      x>=⌈p/i⌉且j>=⌈p/a⌉

      这两个式子是说,x(提醒一下x!=a,x==a一会再另算)要满足要求式必须是在[⌈p/x⌉,2^p]区间内并且被2^⌈p/a⌉整除的整数.

      值得注意的是,如果i=0,即a为奇数,我们回到式②,发现i*x不可能大于等于②,从而没有x!=a满足要求式。对于这种特殊的情况,可以设下边说的那个X在这种情况下为0。

      这样想想,这个问题变成了求一个区间里有多少个某个数的倍数这种问题,就比较显然了。

      满足条件的x!=a的x有X=(2^p/2^⌈p/a⌉-(⌈(p+i-1)/i⌉-1)/2^⌈p/a⌉)个。

      当然,对于x==a的情况,我们单独算一下,是不是已经满足式X,或者不符合x在定义域内的要求。

      如果x符合在定义域内的要求并且不满足式②的话,那么Y=1;否则Y=0。

      我们要求的数就是X+Y了。计算输出它即可。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 long long pingfanmi(long long a,long long b)
     4 {
     5     long long d=b,sum=1;
     6     while(d--)sum*=a;
     7     return sum;
     8 }
     9 int main()
    10 {
    11     int T;
    12     long long a,i,p,temp,s,r,sum;
    13     scanf("%d",&T);
    14     while(T--)
    15     {
    16         sum=0;
    17         scanf("%lld%lld",&a,&p);
    18         s=pingfanmi(2,p);
    19         r=pingfanmi(2,(p+a-1)/a);
    20         temp=a;
    21         for(i=0;temp%2==0;i++,temp/=2);
    22         if(i==0)
    23         {
    24             printf("1
    ");
    25             continue;
    26         }
    27         sum=(s/r-((p+i-1)/i-1)/r);
    28         if(a%r==0&&a<p/i)sum++;
    29         printf("%lld
    ",sum);
    30     }
    31     return 0;
    32 }
    33 //别问我为什么没用快速幂,我懒
  • 相关阅读:
    浓缩版java8新特性
    restful的认识和用法
    常用业务返回对象类ResponseJson
    微信小程序使用websocket通讯的demo,含前后端代码,亲测可用
    完整且易读的最新版小程序登录态和检验注册过没的app.js写法
    完整且易读的微信小程序的注册页面(包含倒计时验证码、获取用户信息)
    BCD工具类(8421)
    IDEA下使用protobuf2(java)
    chrome 调试技巧
    encodeURI和encodeURIComponent的区别?
  • 原文地址:https://www.cnblogs.com/CSGOBESTGAMEEVER/p/10919506.html
Copyright © 2020-2023  润新知