It’s Saturday today, what day is it after 11+22+33+...+NN11+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.
思路:因为发现网上没有一个人的解法是和我的一样的,特写一篇。
设
f(n)=1+22+33+...+nnf(n)=1+22+33+...+nn
本质上是求的是f(n) mod 7f(n) mod 7
本来是我觉得也是要找规律的,但是队友说没有找出额。所以我就开始推该怎么简化这个公式的计算了。
欧拉降幂也想过,后来是就是相当于求1k+2k+..nk1k+2k+..nk感觉写起来比较复杂,需要知道k为2到6的所有的公式,实际上k在3之前的公式我都是知道的,但是后面的就比较复杂,也可以推导。所以放弃了。。。
后来观察到:
ab≡(a mod 7)b(mod 7)ab≡(a mod 7)b(mod 7)
这个证明只需要高中的知识:
a可以写成a=a′+7ka=a′+7k,所以ab=(a′+7k)bab=(a′+7k)b,那么以此二项式展开,除了第一项C0nabCn0ab,其他项都会带有7这个项数,所以都会被7整除,得证。
所以我们就可以按照指数分类了
如:
1+18+115+...+17k−61+18+115+...+17k−6
22+29+216+...+27k−522+29+216+...+27k−5
显然这个就是一个等比数列求和。
我们设首项为ii(1<i<7)ii(1<i<7),当i为1时,就直接求一的个数就可以了,那么公比为i7i7,项的个数为⌊n+7−i7⌋⌊n+7−i7⌋
然后带到设 f(a1,q,n)=ai(qn−1)q−1f(a1,q,n)=ai(qn−1)q−1即可。
所以
ans=⌊n+67⌋+∑i1<i<7f(ii,i7,⌊n+7−i7⌋)ans=⌊n+67⌋+∑i1<i<7f(ii,i7,⌊n+7−i7⌋)
然后记得给ansans对7取模就可以啦。对了因为求和公式有除法,在实现的时候求个对7的逆元就可以啦。哒哒~
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#define mod 7
using namespace std;
char str[10][20] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int P(int a,int b)
{
int ans=1;
while(b)
{
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int inv[8];
int work(int x)
{
int ans=((x+6)/7)%mod;
for(int i=2;i<7;i++)
{
int num=(x+7-i)/7;
int q=P(i,7);
int a1=P(i,i);
ans=(ans+a1*(P(q,num)+6)%mod*P(q+6,5))%mod;
}
return ans;
}
int main() {
int t; scanf("%d", &t);
while(t--) {
int n; scanf("%d", &n);
// printf("%s\n", str[(work(n) + 6) % 7]);
puts(str[(work(n) + 6) % 7]);
}
return 0;
}