[UPC](5222)Sum of the Line ---- 容斥原理★

版权声明:本文为博主原创文章,转载请预先通知博主(〃'▽'〃)。 https://blog.csdn.net/m0_37624640/article/details/82055893

题目链接

Hint: ACM-ICPC 2017 Asia Urumqi: K. Sum of the Line

做法:通过打表或手写,我们很容易发现,第k行的S就是gcd(x,k) = x 的平方和

当k为奇数时,我们可以直接利用   1^2 +2^2 +3^2 +4^2 +...+n^2   = n(n+1)(2n+1)/6 来求

当k为偶数时。比如k = 4时

那一行的T 为 1 0 3 0   S = 1^2+3^2

我们会发现,k的质因子及其倍数是无贡献的,即0

所以这时候我们可以用到容斥原理,如果是k的质因子d

我们就可以剔除d^2 * (1^2+2^2+……+(k/d)^2)

AC代码:

#include<bits/stdc++.h>
#define rep(i,s,t) for(int i = (int)(s); i <= (int)(t); i++)
#define rev(i,t,s) for(int i = (int)(t); i >= (int)(s); i--)
#define pb(x) push_back(x)
#define all(x) x.begin(),x.end()
#define sz(x) (int)(x).size()
using namespace std;
typedef long long ll;
const int mod = 998244353;
const double PI = 4*atan(1.0);
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
int fac[maxn];
ll inv[15];
int cnt;
inline int read()
{
    char x;
    while((x = getchar())<'0' || x>'9');
    int u = x-'0';
    while((x = getchar())>='0' && x<='9') u = (u<<3)+(u<<1)+x-'0';
    return u;
}
void dec(int N)//质因数分解
{
    int t = N;
    for(int j=2;j*j<=t;j++){
        if(t%j == 0){
            fac[cnt++] = j;
            while(t%j == 0) t/=j;
        }
    }
    if(t>1) fac[cnt++] = t;
}
ll calc(int n)//1^2 +2^2 +3^2 +4^2 +...+n^2   = n(n+1)(2n+1)/6
{
    return 1ll*n*(n+1)%mod*(2*n+1)%mod*inv[6]%mod;
}
ll cal(int n) //枚举子集的容斥原理
{
    int flag;
    ll tmp;
    ll sum = 0;
    for(int i=1;i<(1<<cnt);i++)
    {
        tmp = 1; flag = 0;
        for(int j=0;j<cnt;j++)
        {
            if(i&(1<<j)){
                flag++;
                tmp = tmp*fac[j];
            }
        }
        if(flag&1) sum = (sum+(tmp*tmp)%mod*calc(n/tmp))%mod;
        else sum = (sum-(tmp*tmp)%mod*calc(n/tmp)%mod+mod)%mod;
    }
//    cout<<calc(n)<<endl;
//    cout<<sum<<endl;
//    cout<<cnt<<endl;
    return (calc(n)-sum+mod)%mod;
}
void inv_table()
{
    inv[1] = 1;
    for(int i=2;i<=10;i++)
        inv[i] = 1ll*(mod-mod/i)*inv[mod%i]%mod;
}
int main()
{
    #ifdef LOCAL_FILE
    freopen("in.txt","r",stdin);
    #endif // LOCAL_FILE
    int t;
    inv_table();
    t = read();
    while(t--)
    {
        memset(fac,0,sizeof(fac));
        cnt = 0;
        int k = read();
        dec(k);
        printf("%lld\n",cal(k));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37624640/article/details/82055893