TrickGCD HDU

来源:互联网 发布:北京超图软件 编辑:程序博客网 时间:2024/05/29 18:01

又是一道疯狂TLE的题
比赛的思路基本没错,但缺少对时间的优化,只要优化了就ac了,所以没做出这题还是比较可惜的;
一开始我想的是找到所有的质数,然后让他们分别作为gcd的值,后来发现会有重复,就想着改用莫比乌斯反演和容斥定理;

#include <bits/stdc++.h>#define N 100005#define INF 1000000007#define MOD 1000000007using namespace std;typedef long long ll;bool vis[N];int t,prime[N],cnt,n,Time,mu[N],a[N],f[N];ll ans;void init_mu(){    memset(vis,0,sizeof(vis));    mu[1] = 1;    cnt = 0;    for(int i = 2;i < N;i++)    {        if(!vis[i])        {            prime[cnt++] = i;            mu[i] = -1;        }        for(int j = 0;j < cnt && i*prime[j] < N;j++)        {            vis[i*prime[j]] = 1;            if(i % prime[j]) mu[i*prime[j]] = -mu[i];            else             {                mu[i*prime[j]] = 0;                break;            }        }    }}ll ksm(ll x,ll y){    ll ans = 1;    while(y)    {        if(y & 1) ans = ans * x % MOD;        x = x * x % MOD;        y >>= 1;    }    return ans;}int main(){    init_mu();    scanf("%d",&t);    while(t--)    {        ans = 0;        memset(f,0,sizeof(f));        scanf("%d",&n);        int Min = INF;        for(int i = 1;i <= n;i++)         {            scanf("%d",&a[i]);            Min = min(a[i],Min);            f[a[i]]++;        }        for(int i = 1;i <= n;i++) f[i] += f[i-1];        for(int i = 2;i <= Min;i++)        {            ll temp = 1;            for(int j = i;j <= n;j += i) temp = temp * ksm(j/i,f[min(j+i-1,n)] - f[j-1]) % MOD;            ans = (ans + temp*mu[i]*-1 + MOD) % MOD;        }          cout<<"Case #"<<++Time<<": "<<ans<<endl;    }}

如果TLE,还是要多想优化的方法,就像多校1的B题那样。