您的位置:首页 > 其它

ACM-ICPC 2017 Asia Urumqi: K. Sum of the Line(容斥)

2018-02-10 21:38 253 查看
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 Sr​,c, where 1≤rand 1≤c≤r. Sr,c​ is defined as the summation ∑i=ci​Tr,i​.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.

Input

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.

Output

For each case, calculate the summation of elements in the k-th row of S, and output the remainder when it divided by 998244353.

样例输入

2
2
3

样例输出

1
5

题意:如果gcd(r,c)=1,T(r,c)=c;否则T(r,c)=0;S(r,c)=T(r,c)+T(r,c+1)+...T(r,r)。计算SUM(S(k,i))(1<=i<=k)。
思路:考虑基于容斥原理的计算过程。如果 T 中所有位置 T(r,c)=c 总成立,那么答案为1^2+2^2+...+k^2。下面考虑删去 T(r,c)=0 的位置造成的代价。考虑若干两两不同的素数 p1, p2, ..., pu 并记 x=p1p2...pu。则由容斥原理,上述答案需要减去(-1)^(u+1)倍的 x^2(1^2+2^2+...+[k/x]^2)。在 k≤1e8下,u 不超过 9,所以只需要枚举 2^9种可能即可。#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAX= 1e4+100;
typedef long long ll;
int all=0,pr[MAX+100]; //素数表
bool isp[MAX+10];
vector<int>p;
void init()
{
all = 0;
memset(isp,0,sizeof isp);
isp[1]=1;
for(int i=2;i<=MAX;i++)
{
if(!isp[i])pr[all++] = i;
for(int j=0;j<all;j++)
{
long long t = 1LL*pr[j]*i ;
if(t<=MAX)
{
isp[t] = true;
if(i%pr[j]==0)break;
}
else break;
}
}
return ;
}
void div(int x) //分解成素数
{
for(int i = 0; i < all && x > 1; i++)
{
if(x%pr[i]==0)p.push_back(pr[i]);
while( x % pr[i] == 0)x /= pr[i];
}
if(x > 1)p.push_back(x);
}
ll cla(ll n)//计算1^2+2^2+3^2+....+n^2
{
ll ans=n*(n+1)/2;
if(ans%3==0)
{
ans/=3;
return (ans%MOD)*((2*n+1)%MOD)%MOD;
}
return (ans%MOD)*(((2*n+1)/3)%MOD)%MOD;
}
ll f(int x)
{
ll ans=1;
for(int i=0;i<p.size();i++,x/=2)if(x%2)ans*=p[i];
return ans;
}
int main()
{
init();
int T;cin>>T;
while(T--)
{
int k;
scanf("%d",&k);
p.clear();
div(k);
ll ans=cla(k);
for(int i=1;i<(1<<(p.size()));i++)
{
ll a=f(i);
if(__builtin_popcount(i)%2==0)ans+=(a*a%MOD)*cla(k/a)%MOD;//__builtin_popcount(i)计算i的二进制数中1的个数
else ans-=(a*a%MOD)*cla(k/a)%MOD;
ans%=MOD;
ans=(ans+MOD)%MOD;
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐