HDU 6134 && 2017 多校訓練:Battlestation Operational(莫比烏斯反演+積性函式)
阿新 • • 發佈:2019-02-15
實在太長了直接放題目連結
這題就是求
考慮當Gcd(i, j)==1時,除了j為1的情況,其它時候i/j一定是小數,所以i/j向上取整相當於向下取整的結果+1
那麼有:(其中φ(i)為小於i與i互質的對數,即尤拉函式)
尤拉函式因為是積性函式,可以線性求出,令
為什麼上面等式成立?
對於所有的n/i,當n和i不互質時,很顯然它們除掉它們的Gcd之後就互質了,而等式左邊正是在列舉n的約數
那麼有:
其中莫比烏斯函式和原公式中的尤拉函式都可以O(n)預處理
這樣只要列舉後半部分就可以得出答案了
但很可惜這樣複雜度仍然是O(nsqrt(n))的所以比賽中就超時了。。。
卡了好久好久好久。。。
繼續想:
上面公式還可以轉
其中τ(n)表示n的約數個數,是積性函式也可以線性求出
那麼答案有
其中先預處理τ(n)的字首和,再預處理u(i)與t(n)字首和積的字首和
最後帶上尤拉函式再算一波字首和即可
直接O(1)查詢,程式碼很短,就是做了2個半小時。。。
#include<stdio.h> #include<string.h> #define mod 1000000007 #define LL long long LL cnt[1000005], sum[1000005] = {0,1}, ans[1000005] = {0,1}; int main(void) { LL n, i, j; for(i=1;i<=1000000;i++) { for(j=i;j<=1000000;j+=i) cnt[j]++; } for(i=2;i<=1000000;i++) sum[i] = (sum[i-1]+cnt[i-1]+1)%mod; for(i=1;i<=1000000;i++) { for(j=i+i;j<=1000000;j+=i) sum[j] = ((sum[j]-sum[i])%mod+mod)%mod; } for(i=2;i<=1000000;i++) ans[i] = (sum[i]+ans[i-1])%mod; while(scanf("%lld", &n)!=EOF) printf("%lld\n", ans[n]); return 0; }