hdu5690 快速幂+求模化简

4 篇文章 0 订阅
1 篇文章 0 订阅

上面那个式子,分子分母同乘一个9后,余数最终要除回一个9。

#include <cstdio>

int t;
long long x, m, k, c;

long long quickpowmod(long long x, long long y, long long mod)
{
    long long ret = 1;
    while(y){
        if(y&1)
            ret = ret*x%mod;
        x = x*x%mod;
        y >>= 1;
    }
    return ret;
}

int main()
{
    scanf("%d", &t);
    int cn = 0;
    while(t--){
        scanf("%I64d%I64d%I64d%I64d", &x, &m, &k, &c);
        printf("Case #%d:\n", ++cn);
        long long mod = 9*k;
        long long p = quickpowmod(10, m, mod);
        if((p-1)*x%mod%mod == 9*c)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

如果对求模化简不太熟悉,可以用循环节的思路。

思路:因为是相同的数字组成的数,所以如果某一个余数之前出现过了,后面必然相同,即有循环节。所以只需要记录循环节就可以。

以下参考了大神的代码的思路:一个数 mod p,余数只能是0到p-1,这P个数,也就是说循环节最大只能是p,所以我们假定循环节就是P,就不用分别求循环节了,并且不用对一个数求余时进行讨论。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e4+50;
int t,x,c,k,res;
long long m;
int cir[maxn];///cir存储循环节 

int main(){
	while(scanf("%d",&t)!=EOF){
		for(int cas=1;cas<=t;cas++){
			memset(cir,-1,sizeof(cir));
			scanf("%d%lld%d%d",&x,&m,&k,&c);
			res=0; 
			for(int i=0;i<k;i++){
				res=(res*10+x)%k;
				cir[i]=res;
			}
			m--;///与循环节位置对齐 
			printf("Case #%d:\n",cas);
			if(cir[m%k]==c) printf("Yes\n");
			else printf("No\n");
		}
	}
	return 0;
}

总结:遇到这种类数论题目,目前为止的解决方法有:

1、找规律,如本题可以通过寻找循环节来解决。(先想有没有最大循环节,这样可以避免讨论一些特殊的细节情况)

2、对式子进行化简转化为更容易解决的

3、想想是不是可以数位dp



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值