循环节 - 【数论】

循环节

引言:
小学的规律题大家不陌生吧,经常跟取余数挂钩的那种,其实挺简单的。比如给你一个序列1 3 5 7 9 1 3 5 7 9 1 3 …这就是小学题目嘛,对吧看着好简单。
循环节:
其实现在很多题目也要用到同样的方法,打表找出循环节点,然后再去处理它。这类题目往往有些特点,数据大,结果取模。
例题:
All X:hdu 5690

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

F(x,m) mod k ≡ c

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

1≤x≤9

1≤m≤1010

0≤c<k≤10,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”。

代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e7+5;
const int inf=0x3f3f3f3f;
int f[maxn];
int main(){
	ll t;
	ll x,m,k,c;
	scanf("%lld",&t);
	for(ll i=1;i<=t;i++){
		scanf("%lld%lld%lld%lld",&x,&m,&k,&c);
		printf("Case #%d:\n",i);
		f[1]=x%k;
		int j;
		for(j=2;j<maxn;j++){
			f[j]=(f[j-1]*10+x)%k;
			if(f[j]==f[1]) break;
		}
		m=m%j;
		if(f[m]==c) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

说明:
上代码中循环节就是j,对于这类题目只能这样打表去试探…要注意那个里面递推对的过程,只对最外层取模就可以了,因为模运算其实很慢的,我当时多取了两个,t了很多次。

发布了43 篇原创文章 · 获赞 56 · 访问量 5108

猜你喜欢

转载自blog.csdn.net/tran_sient/article/details/97755975