ZOJ 3785 What day is that day?(费马小定理智寻循环节)

Description

It's Saturday today, what day is it after 11 + 22 + 33 + ... + NN days?

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

There is only one line containing one integer N (1 <= N <= 1000000000).

Output

For each test case, output one string indicating the day of week.

Sample Input

2
1
2

Sample Output

Sunday
Thursday
Hint

A week consists of Sunday, Monday, Tuesday, Wednesday, Thursday, Friday and Saturday.

这道题看网上很多人用暴力求得循环节为294,这个做法不太通用。其实这道题的循环节是有办法可以找到的。

这里可以利用一个公式费马小定理:a^(n-1)%n=1(n为素数)


我们知道n^n%7=(n%7)^n%7,令n%7=m,则原式=(m^m%7)*(m^(n-m)%7)%7

举个例子,9^9%7=2^9%7=((2^2%7)*(2^7%7))%7,所以只要让(2^7%7)这个部分等于1,而且这一部分,2的幂肯定是7的倍数(自己证),那么循环节就出现了,循环节的开端为m^m%7(m<7)。我们知道(2^a%7)^b%7=2^ab%7,让该公式为1,且ab为7的倍数,则a等于6,得ab的最小值为42,所以n^n%7的循环节为42

294=42*7,即为11 + 22 + 33 + ... + NN %7的循环节


代码:

#include<iostream>
#include<string>
using namespace std;

template<class T, class D>
T qpow(T a, D n, int mod)
{
	if (n == 0) return 1;
	T ans;
	ans = qpow(a, n / 2, mod);
	ans = ans*ans;
	ans = ans%mod;
	if (n % 2 != 0)
	{
		ans = ans*a;
		ans = ans%mod;
	}
	return ans;
}

int main()
{
	string week[7]={"Saturday","Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
	int list[43];
	for(int i=1;i<43;i++) list[i]=qpow(i,i,7);
	int cycle[43];
	cycle[0]=0;
	for(int i=1;i<43;i++) cycle[i]=(cycle[i-1]+list[i])%7;	
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		int a,b,sum;
		a=n/42;
		b=n%42;
		sum=(cycle[42]*a%7+cycle[b])%7;
		cout<<week[sum]<<endl; 
	}
	return 0;
}
里面写得有点水,其实中间那个求幂是可以优化的,大家可以想想






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值