題面:
王老師 最近做了一道經典問題《翻紙牌》
現在 王老師 有 n 張牌,編號分別為 1,2,3…n,每張牌一開始都是背面朝上的
現在他要進行 n 輪操作,第 i 輪操作時候,他會將所有編號是 i 的倍數的牌正反翻面
現在 王老師 想知道,當他進行完 n 輪操作以後,所有正面朝上的牌的編號總和是多少
因為數字可能很大,所以請你將答案對 109+7 取模
對於 30% 的資料:1≤n≤106
對於 60% 的資料:1≤n≤1014
對於 100% 的資料:1≤n≤1018
從題中可知將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;
}
總結:在做題時需觀看資料量判斷其會不會爆,在進行處理,我在估資料量時還是比較弱,以後在打程式碼前應估計在中途會不會爆,再寫程式碼。