记录循环节+数论________All X( hdu 5690 2016百度之星初赛A )
2016-06-10 14:53
337 查看
Problem Description
F(x,
m)F(x,m) 代表一个全是由数字xx组成的mm位数字。请计算,以下式子是否成立:
F(x,m)\
mod\ k\ \equiv \ cF(x,m) mod k ≡ c
Input
第一行一个整数TT,表示TT组数据。
每组测试数据占一行,包含四个数字x,m,k,cx,m,k,c
1\leq
x\leq 91≤x≤9
1\leq
m\leq 10^{10}1≤m≤1010
0\leq
c< k\leq 10,0000≤c<k≤10,000
Output
对于每组数据,输出两行: 第一行输出:"Case #i:"。ii代表第ii组测试数据。
第二行输出“Yes” 或者 “No”,代表四个数字,是否能够满足题目中给的公式。
Sample Input
Sample Output
对于第一组测试数据:111 mod 5 = 1,公式不成立,所以答案是”No”,而第二组测试数据中满足如上公式,所以答案是 “Yes”。
分析:
(a+b)%c = (a%c+b%c)%c
原本以为是一个裸的数论的题目结果发现m有点大,不能直接for循环m次求答案。但是还好的是k 比较小。那么我们就可以找f(x,m)%k值的循环节。我们知道这个循环节肯定小于等于k.所以我们最多for循环k次就可以得到循环节t。然后就通过m%t.得到循环节中的具体值。
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include <cstdio>
#include<cmath>
using namespace std;
int a[10010];
int b[10010];
int main()
{
int t,Case = 0;
cin >> t;
while(t--)
{
int x,c,k,top = 1;
long long m;
scanf("%d%lld%d%d",&x,&m,&k,&c);
memset(a,0,sizeof(a));
int sum = 0;
a[0] = 1;
int flag = 0;
for(long long i = 0 ; i < m ; i ++)
{
sum = (sum * 10 + x)% k;
if(i + 1 == m && sum == c)
{
flag = 1;
break;
}
if(a[sum] == 1)
{
//b[0]~b[top-1].循环节为top;
if(b[m%top] == c)
{
flag = 1;
}
break;
}
else
{
a[sum] = 1;
b[top++] = sum;
}
}
printf("Case #%d:\n%s\n",++Case,flag?"Yes":"No");
}
return 0;
}
/*
1
1 10000000002 3 0
*/
F(x,
m)F(x,m) 代表一个全是由数字xx组成的mm位数字。请计算,以下式子是否成立:
F(x,m)\
mod\ k\ \equiv \ cF(x,m) mod k ≡ c
Input
第一行一个整数TT,表示TT组数据。
每组测试数据占一行,包含四个数字x,m,k,cx,m,k,c
1\leq
x\leq 91≤x≤9
1\leq
m\leq 10^{10}1≤m≤1010
0\leq
c< k\leq 10,0000≤c<k≤10,000
Output
对于每组数据,输出两行: 第一行输出:"Case #i:"。ii代表第ii组测试数据。
第二行输出“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: YesHint
对于第一组测试数据:111 mod 5 = 1,公式不成立,所以答案是”No”,而第二组测试数据中满足如上公式,所以答案是 “Yes”。
分析:
(a+b)%c = (a%c+b%c)%c
原本以为是一个裸的数论的题目结果发现m有点大,不能直接for循环m次求答案。但是还好的是k 比较小。那么我们就可以找f(x,m)%k值的循环节。我们知道这个循环节肯定小于等于k.所以我们最多for循环k次就可以得到循环节t。然后就通过m%t.得到循环节中的具体值。
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include <cstdio>
#include<cmath>
using namespace std;
int a[10010];
int b[10010];
int main()
{
int t,Case = 0;
cin >> t;
while(t--)
{
int x,c,k,top = 1;
long long m;
scanf("%d%lld%d%d",&x,&m,&k,&c);
memset(a,0,sizeof(a));
int sum = 0;
a[0] = 1;
int flag = 0;
for(long long i = 0 ; i < m ; i ++)
{
sum = (sum * 10 + x)% k;
if(i + 1 == m && sum == c)
{
flag = 1;
break;
}
if(a[sum] == 1)
{
//b[0]~b[top-1].循环节为top;
if(b[m%top] == c)
{
flag = 1;
}
break;
}
else
{
a[sum] = 1;
b[top++] = sum;
}
}
printf("Case #%d:\n%s\n",++Case,flag?"Yes":"No");
}
return 0;
}
/*
1
1 10000000002 3 0
*/
相关文章推荐
- 1.m分解阶乘之和
- 2.几种递推数
- 3.欧拉函数
- 4.快速幂模m算法
- 5.扩展欧几里得&&中国剩余定理
- 6.数论_web
- Project Euler Problem 387 - Harshad Numbers - 深度优先
- 编程之美2015初赛A
- 数论题集
- 原根
- 阶与原根学习笔记
- HDU 1299 Diophantus of Alexandria
- Leftmost Digit(HDU 1060)
- Rightmost Digit(HDU 1061)
- Python-在奇数中寻找素数
- ZOJ 2674 Strange Limit 欧拉定理
- LeetCode-Palindrome Number
- 组合数求模总结
- Sicily 1047 Super Snooker
- SGU 181 X-Sequence(傻逼题)