What day is that day? ZOJ - 3785 (数学)(二项式)(等比数列求和)

本文介绍了一种通过模7运算求解特定数列和的方法,并给出了一种高效的算法实现。该算法利用等比数列求和原理,通过分类讨论简化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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+...+17k61+18+115+...+17k−6
22+29+216+...+27k522+29+216+...+27k−5
显然这个就是一个等比数列求和。
我们设首项为ii(1<i<7)ii(1<i<7),当i为1时,就直接求一的个数就可以了,那么公比为i7i7,项的个数为n+7i7⌊n+7−i7⌋
然后带到设 f(a1,q,n)=ai(qn1)q1f(a1,q,n)=ai(qn−1)q−1即可。
所以
ans=n+67+i1<i<7f(ii,i7,n+7i7)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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值