Sum of the Line(ICPC2017 Urumqi)
https://www.jisuanke.com/contest/1409/challenges
题目描述
Consider a triangle of integers, denoted by T. The value at (r, c) is denoted by Tr,c , where 1 ≤ r and 1 ≤ c ≤ r. If the greatest common divisor of r and c is exactly 1, Tr,c = c, or 0 otherwise.
Now, we have another triangle of integers, denoted by S. The value at (r, c) is denoted by S r,c , where 1 ≤ r and 1 ≤ c ≤ r. S r,c is defined as the summation
Here comes your turn. For given positive integer k, you need to calculate the summation of elements in k-th row of the triangle S.
Now, we have another triangle of integers, denoted by S. The value at (r, c) is denoted by S r,c , where 1 ≤ r and 1 ≤ c ≤ r. S r,c is defined as the summation
Here comes your turn. For given positive integer k, you need to calculate the summation of elements in k-th row of the triangle S.
输入
The first line of input contains an integer t (1 ≤ t ≤ 10000) which is the number of test cases.
Each test case includes a single line with an integer k described as above satisfying 2 ≤ k ≤ 10^8 .
Each test case includes a single line with an integer k described as above satisfying 2 ≤ k ≤ 10^8 .
输出
For each case, calculate the summation of elements in the k-th row of S, and output the remainder when it divided
by 998244353.
by 998244353.
样例输入
2
2
3
样例输出
1
5
题意:对于gcd(i,k) == 1,则S(i,k) = i,否则为0,求S = sigma(S(i,k)^2)
题解:
如果没有gcd(i,k)这个限制,则答案就为signa(i^2) 即sigma(i^2) = n*(n+1)*(2*n+1)/6
gcd(i,k) != 1,说明i 与 k 存在共同的因子(除1外),对于n(<=1e8)的最多的素因子不超过10个,对因子进行容斥
可以表示为:|U| - |A∪B∪C∪....∪Z| ,A ,B ,...., Z 分别表示为能被某个素数整除的
首先将k中素因子筛选出来,用唯一分解定理,然后对这些因子进行容斥,可以dfs,也可以用二进制 (0,1表示取或不取,但必须保证至少取一次)
AC code:
#include <iostream> #include <cstdio> using namespace std; const int MAXN = 10000000; const int mod = 998244353; typedef long long ll; ll fast_pow(ll a,ll n) { ll ans = 1; while(n) { if(n&1) ans = (ans * a)%mod; a = (a * a)%mod; n >>= 1; } return ans; } const ll six = fast_pow(6,mod-2); int main() { int t; scanf("%d",&t); while(t--) { int tot = 0; ll n,k; scanf("%lld",&k); n = k; int prime[100]; for(int i = 2;i * i <= n;i++) { if(n % i == 0) { prime[tot++] = i; while(n % i == 0) n /= i; } } if(n != 1) prime[tot++] = n; ll ans = k*(k+1)%mod*(2*k+1)%mod*six%mod; for(int i = 1;i < (1<<tot);i++) { n = i; int pos = tot - 1,cnt = 0; ll ant = 1; while(n) { if(n&1) ant *= prime[pos],cnt++; pos--; n >>= 1; } ll m = k/ant; if(cnt&1) ans = (ans - ant*ant%mod*m%mod*(m + 1)%mod*(2*m + 1)%mod*six%mod + mod)%mod; else ans = (ans + ant*ant%mod*m%mod*(m + 1)%mod*(2*m + 1)%mod*six%mod)%mod; } printf("%lld\n",ans); } }