@ACM-ICPC 2017 Asia Urumqi(乌鲁木齐): K. Sum of the Line (容斥原理)

版权声明:岂曰无衣,与子同袍 https://blog.csdn.net/sizaif/article/details/81913580

 K: Sum of the Line

时间限制: 1 Sec  内存限制: 128 MB
提交: 93  解决: 18
[提交] [状态] [讨论版] [命题人:admin]

题目描述

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.

输入

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 .

输出

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

题意:

求 \sum_{1}^{k}{S(k,i)} = \sum_{1}^{k} \sum_{1}^{c}T(k,i)       T(k,i)定义为 :  若 gcd 为1  则为 i  否则 为 0 '

类似:

T(1,1)

T(2,2) T(2,2)

T(3,3) T(3,3) T(3,3) 

T(4,4) T(4,4) T(4,4) T(4,4) 

....

T(K,K) T(K,K) T(K,K) T(K,K)

思路: 容斥原理:

可以先求 总的 sum  =  1^2 + 2^2 + 3^2 + 4^2+5^2 +...... k^2 = \frac{n(n+1)(2n+1) }{ 6}  

然后 减去 容斥的部分 就可以了,

需要把  质因子 以及其倍数所在的那一行 求出;

对每一个质因子 式子为: (p*1)^2 + (p*2)^2 + (p*3)^2 +.... (p * n/p)^2

提取 p^2 得: p^2(1^2+2^2+3^2+4^2+....(\frac{n}{p})^2) 然后 在套用 公式 ,求

转化成 求 k 的质因子,   每一个质因子 就是  容斥的一部分,    

然后 需要做的操作是 对与 所有的质因子,  取 任意两个, 任意三个, 任意四个, 到 任意n个 的 倍数, 这是重复的部分, 这里

因为1e8 的质因子最多有9个 , 所以可以采取 暴力 二进制 枚举01  ,判断

容斥时 遵循  :  奇数减  偶数加的 原则。

具体 看代码:

代码:

#include <bits/stdc++.h>
#include <stdio.h>
#define rep(i,a,n) for(int i = a;i<=n;i++)
using namespace std;
const int maxn = 1e8+10;
const int mod = 998244353;
typedef long long ll;

inline ll qpow(ll a,ll n)
{
	ll res = 1;
	for(;n;n>>=1)
	{
		if(n&1)
			res = res*a %mod;
		a = a*a%mod;
	}
	return res;
}

ll GetSum(ll n)
{
	return ( (n*(n+1)%mod*(2*n+1ll)%mod)*qpow(6ll,mod-2)%mod)%mod;
}
ll a[200];
int k ;
void table(ll n)
{
	ll temp=n;
    if(temp%2==0)
    {
        a[k++]=2;
        while(temp%2==0)
            temp/=2;
    }

    for(int i=3;i<=sqrt(n)+1;i+=2)
    {
        if(temp%i==0)
        {
            a[k++]=i;
            while(temp%i==0)
                temp/=i;
        }
    }
    if(temp!=1)
        a[k++]=temp;
	
}

int main(int argc, char const *argv[])
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		ll n;
		k = 0;
		memset(a,0,sizeof(a));
		scanf("%lld",&n);
		table(n);
		ll sum  = GetSum(n);
		int binary[100];
		ll res = 0;
		for(int i = 0;i < k;i++)
		{
			////////
			//cout<<"VVV "<<a[i]<<endl;
			////////
			ll up = 1ll*n/a[i];
			ll tep = qpow(1ll*a[i],2ll)*GetSum(up)%mod;
			res = (res +  tep )%mod;	
		}
		int bi = 0;
		for(int i = 0 ; i < qpow(2ll,k);i++)
		{
			int te = i;
			while(te)
			{
				binary[bi++] = te%2;
				te/=2;
			}
			int num = 0 ;
			ll rsum = 1;
			rep(j,0,bi-1)
			{
				if( binary[j]==1)
				{
					num++;
					rsum *= a[j];
				}
			}
			bi = 0;

			if( num < 2 || rsum > n )
				continue;
			int dc = 1;
			if( num%2==0)
			{
				ll up = 1ll*n/rsum;
				res = (res - qpow(1ll*rsum,2ll)*GetSum(up))%mod;
			}
			else
			{
				ll up = 1ll*n/rsum;
				res = (res + qpow(1ll*rsum,2ll)*GetSum(up))%mod;
			}
		}
		//cout<<sum<< " "<<res<<endl;
		printf("%lld\n",(sum-res+mod)%mod );
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sizaif/article/details/81913580