新赛道-2024.8 CSP-J组月赛-T1总结

题面:

王老师 最近做了一道经典问题《翻纸牌》

现在 王老师 有 n 张牌,编号分别为 1,2,3n,每张牌一开始都是背面朝上的

现在他要进行 n 轮操作,第 i 轮操作时候,他会将所有编号是 i 的倍数的牌正反翻面

现在 王老师 想知道,当他进行完 n 轮操作以后,所有正面朝上的牌的编号总和是多少

因为数字可能很大,所以请你将答案对 109+7 取模

对于 30% 的数据:1n106

对于 60% 的数据:1n1014

对于 100% 的数据:1n1018

从题中可知将n翻面的只有n的因子,而翻到正面的数字的因子个数一定是奇数,也就是完全平方数,再套入公式:n*(n+1)*(2*n+1)/6即可,但数据量为1e18,这么算会爆long long (我就是这么写挂的。。),所以需要用到特殊处理,首先,我们知道n*(n+1)%2==0,所以可以先算n*(n+1)/2,剩下的/3分两种情况讨论

设v=sqrt(n),x=v*(v+1)/2

1.若x%3==0,那么直接先将x/3%mod*(2*v+1)%mod;

2.否则把/3丢给(2*v+1):x%mod*((2*v+1)/3)%mod

代码:

#include <bits/stdc++.h>
using namespace std;
const unsigned long long mod=1e9+7;
unsigned long long n;
int main(){
  //freopen("card.in","r",stdin);
  //freopen("card.out","w",stdout);
  ios::sync_with_stdio(0);
  cin.tie(0);cout.tie(0);
  cin>>n;
  unsigned long long op=sqrt(n);
  unsigned long long ans=op*(op+1)/2;
  if(ans%3==0)cout<<ans/3%mod*(2*op+1)%mod;
  else cout<<ans%mod*((2*op+1)/3)%mod;
  return 0;
}

总结:在做题时需观看数据量判断其会不会爆,在进行处理,我在估数据量时还是比较弱,以后在打代码前应估计在中途会不会爆,再写代码。

posted @ 2024-09-01 10:53  谦谦2020  阅读(41)  评论(0编辑  收藏  举报