hnust - 取模方程解的个数 - 类似高次方数 - 快速幂取模

题目描述

给定x和m,问在区间[a,b]上存在多少个i,使得xi % 1000 = m。

输入
输入由多组数据构成。
每组数据一行,由四个空格分开的整数x、m、a和b组成。
0 <= x, m <= 1000000000
1 <= a <= b <= 1000000000

输出
每组输入数据产生一行输出,即使得上述等式成立的i的个数。

样例输入
13 13 1 100
13 12 1 100
13 13 1 1000000000
样例输出
1
0
10000000
##题解

  • i∈(a,b),(b)max=1000000000.肯定要用到快速幂并且取模1000;
  • 取模1000,很明显的知道,m的取值范围为(0,999)。所以∀m>=1000,ans=0;
  • 验证规律性。
int x=13
int a=1,b=200;
for(int i=a;i<=b;i++){
        cout<<pow_mod(x,i,1000)<<",";
    }
13,169,197,561,293,809,517,721,373,849,37,481,253,289,757,841,933,129,677,801,413,369,797,361,693,9,117,521,773,49,637,281,653,489,357,641,333,329,277,601,813,569,397,161,93,209,717,321,173,249,237,81,53,689,957,441,733,529,877,401,213,769,997,961,493,409,317,121,573,449,837,881,453,889,557,241,133,729,477,201,613,969,597,761,893,609,917,921,973,649,437,681,853,89,157,41,533,929,77,1,13,169,197,561,293,809,517,721,373,849,37,481,253,289,757,841,933,129,677,801,413,369,797,361,693,9,117,521,773,49,637,281,653,489,357,641,333,329,277,601,813,569,397,161,93,209,717,321,173,249,237,81,53,689,957,441,733,529,877,401,213,769,997,961,493,409,317,121,573,449,837,881,453,889,557,241,133,729,477,201,613,969,597,761,893,609,917,921,973,649,437,681,853,89,157,41,533,929,77,1,

看出每隔100个数就会出现一次13。可能这个时候你会觉得答案就在眼前,但结果告诉你“答案错误”,因为并不是所有的数每隔100次就出现一次,也不是每个数就会多次出现。
不信再试试n=2,它的前几项里,2和4是只出现一次的,只有从数字8开始才出现的循环。分析到这里基本够了。
还有一个可以证明的是,如果一个数在200次内没有出现重复的数,他就不会有重复的数了。

  • 编程的实现问题,①m>=1000,输出ans=0。②0< m<1000,算出m重复出现的间隔,不重复出现输出0,有间隔则输出[a,b]区间内能满足的次数。
    代码
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
typedef long long ll;
// (a-2b)(c^2-3ad+d^3)=0
int main()
{
  ll n, ans;
  while(~scanf("%lld",&n)){
    ll a, c, d;
    ans = n / 2;//有多少组a=2b的解
    ans *= n * n;//a=2b后,因为cd可以任意取1~n,
    ll maxd=sqrt(3*n+1);//3*d-d*d*d<=c*c
    for(d = 1; d<=maxd; d++)//限制d范围
        for(c = 1; c <= n; c++){//对c^2-3ad+d^3=0的解枚举
        a = d * d * d + c * c;
        if(a % (3 * d) == 0){
            a/=(3 * d);
            //printf("%d %d %d\n",c,d,a);
            if(a>=1 && a <= n){
                ans += n;
                if(a % 2 == 0)//a为偶数,即减去已算过的a=2b的数
                    ans--;
            }
        }
    }
    printf("%lld\n",ans);
  }
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值