HDU 5690——All X——————【快速幂 | 循环节】

All X

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 879    Accepted Submission(s): 421


Problem Description
F(x,m) 代表一个全是由数字x组成的m位数字。请计算,以下式子是否成立:

F(x,m) mod k  c
 
Input
第一行一个整数T,表示T组数据。
每组测试数据占一行,包含四个数字x,m,k,c

1x9 

1m1010

0c<k10,000
 
Output
对于每组数据,输出两行:
第一行输出:"Case #i:"。i代表第i组测试数据。
第二行输出“Yes” 或者 “No”,代表四个数字,是否能够满足题目中给的公式。
 
Sample Input
3
1 3 5 2 1 3 5 1 3 5 99 69
 
Sample Output
Case #1: No Case #2: Yes Case #3: Yes
Hint
对于第一组测试数据:111 mod 5 = 1,公式不成立,所以答案是”No”,而第二组测试数据中满足如上公式,所以答案是 “Yes”。
 
Source
 
 
解题思路:打表找循环节。
 
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<string>
#include<iostream>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
using namespace std;
typedef long long LL;
#define mid (L+R)/2
#define lson rt*2,L,mid
#define rson rt*2+1,mid+1,R
#pragma comment(linker, "/STACK:102400000,102400000")
const int maxn = 1e5 + 300;
const LL INF = 0x3f3f3f3f;
typedef long long  LL;
typedef unsigned long long ULL;
LL vis[maxn], a[maxn];
int main(){
    LL x, m, k, c;
    int T, cas = 0;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%lld%lld",&x,&m,&k,&c);
        memset(vis,0,sizeof(vis));
        int nn = 0, le = 0, st = 1;
        LL cc;
        LL n = 0;
        for(int i = 1; ; i++){
            n = n*10;
            n = n + x;
            n = n%k;
            if(vis[n]){
                cc = n;
                break;
            }else{
                vis[n] = 1;
                nn++;
                a[nn] = n;
            }
        }
        for(int i = 1; i <= nn; i++){
            if(a[i] == cc){
                le = nn+1 - i;
                st = i;
                break;
            }
        }
        int flag = 0;
        if(m < st){
            if(a[m] == c){
                flag = 1;
            }
        }else{
            m -= st;
            m %= le;
            if(a[st+m] == c){
                flag = 1;
            }
        }
        printf("Case #%d:
",++cas);
        if(flag) puts("Yes");
        else puts("No");
    }
    return 0;
}



/*
55
3 5 99 69

3 4 4 2
3 8 4 2

2 8 3 2

*/

  

解题思路:数学方法。

转自http://m.blog.csdn.net/article/details?id=51471639

这个数要mod k ,那这个数应该怎么表示呢?

就这样转化了,然后10^m可以通过快速幂解决,但是很明显,除以9操作怎么办,除法取模,余数是会改变的,逆元?但是9和k不一定互质,且k也不一定是质数,所以扩展欧几里得和费马小定理都不能用了,束手无策

好吧,这里提供一种小方法

就这样经过几步转化,我求d不需要进行除法取模了,那我上面的问题不就解决了?对的。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<string>
#include<iostream>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
using namespace std;
typedef long long LL;
#define mid (L+R)/2
#define lson rt*2,L,mid
#define rson rt*2+1,mid+1,R
#pragma comment(linker, "/STACK:102400000,102400000")
const int maxn = 1e5 + 300;
const LL INF = 0x3f3f3f3f;
typedef long long  LL;
typedef unsigned long long ULL;
LL quick(LL x,LL n,LL p){
    if(n == 0) return 1;
    LL ret = 1;
    while(n){
        if(n&1) ret = ret*x % p;
        n = n >> 1;
        x = x*x % p;
    }
    return ret;
}
int main(){
    LL x, m, k, c;
    int T, cas = 0;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%lld%lld",&x,&m,&k,&c);
        k*=9;
        LL ans = quick(10,m,k);
        ans = (ans - 1 + k) % k;
        ans /= 9;
        k /= 9;
        ans = ans * x % k;
        bool flag = 0;
        if(ans == c)
            flag = 1;
        printf("Case #%d:
",++cas);
        if(flag) puts("Yes");
        else puts("No");
    }
    return 0;
}

 

  

原文地址:https://www.cnblogs.com/chengsheng/p/5521041.html