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;
}
里面写得有点水,其实中间那个求幂是可以优化的,大家可以想想