• FR #12题解


    A.

      我的做法是nmlogn的。。。。直接做m次堆贪心就可以。按理说是能过的。。。

          正解直接是在原dp上搞一搞。。。可以做到n^2+nlog?

          2333

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define maxn 2050
    using namespace std;
    long long n,m,a[maxn];
    long long now=0;
    struct status
    {
        long long id,val;
        status (long long id,long long val):id(id),val(val) {}
        status () {}
        friend bool operator < (status x,status y)
        {
            return x.val>y.val;
        }
    };
    priority_queue <status> q;
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for (long long i=1;i<=n;i++) scanf("%lld",&a[i]);
        for (long long i=1;i<=m;i++)
        {
            scanf("%lld",&now);long long ret=0;
            while (!q.empty()) q.pop();
            for (long long j=1;j<=n;j++)
            {
                if (now+a[j]>=0)
                {
                    now+=a[j];
                    if (a[j]<0) q.push(status(j,a[j]));
                }
                else
                {
                    ret++;
                    if (!q.empty())
                    {
                        if (now-q.top().val+a[j]>=now)
                            {now=now-q.top().val+a[j];q.pop();q.push(status(j,a[j]));}
                    }
                }
            }
            printf("%lld
    ",ret);
        }
        return 0;
    }

    B.

      第一问的话,可以用phi(a*b)=phi(a)*phi(b)*gcd(a,b)/phi(gcd(a,b)),那么可以筛出所有需要的东西。

          至于第二问。。参照上帝与集合的正确用法。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 10000050
    #define mod 1000000007
    using namespace std;
    int n,m,k=0,p,prime[maxn],tot=0,d[maxn],phi[maxn],inv[maxn];
    bool vis[maxn];
    int gcd(int a,int b)
    {
        if (!b) return a;
        return gcd(b,a%b);
    }
    void get_table()
    {
        phi[1]=inv[1]=d[1]=1;
        for (register int i=2;i<=maxn-50;i++)
        {
            inv[i]=(-(long long)mod/i*inv[mod%i]%mod+mod)%mod;
            if (!vis[i])
            {
                prime[++tot]=i;
                phi[i]=i-1;
                if (n%i==0) d[i]=i;else d[i]=1;
            }
            for (register int j=1;j<=tot && i*prime[j]<=maxn;j++)
            {
                vis[i*prime[j]]=true;
                if ((n/d[i])%prime[j]==0) d[i*prime[j]]=d[i]*prime[j];
                else d[i*prime[j]]=d[i];
                if (i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1);
                else
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
            }
        }
    }
    long long f_pow(long long x,long long y,long long p)
    {
        long long ans=1,base=(long long)x;
        while (y)
        {
            if (y&1) ans=(ans*base)%p;
            base=(base*base)%p;
            y>>=1;
        }
        return ans;
    }
    void work1()
    {
        for (int i=1;i<=m;i++)
        {
            long long ret=(((long long)phi[i]*phi[n])%mod*d[i])%mod*inv[phi[d[i]]]%mod,ret2;
            k=((int)ret+k)%mod;
        }
    }
    int work2(int p)
    {
        if (p==1) return 0;
        return f_pow(k,work2(phi[p])+phi[p],p);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&p);
        get_table();
        work1();
        printf("%d
    ",work2(p));
        return 0;
    }

    C.

      还是数学题。。。。

          gcd(f[a],f[b])=f[gcd(a,b)]。

          lcm(a,b,c)=a*b*c/gcd(a,b)/gcd(a,c)/gcd(b,c)*gcd(a,b,c)。

          那么可以g[i]表示F[i]的幂次。首先g[i]+g[2*i]+...=Σ(i=1..n)(-1)^(n+1)*C(n,i)=[n!=0]。

          所以倒着for,调和级数搞一搞就好了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 50050
    #define maxm 1000050
    #define mod 1000000007
    using namespace std;
    long long n,a[maxn],cnt[maxm],num[maxm],g[maxm],mx=0,f[maxm];
    long long ans=1;
    long long f_pow(long long x,long long y)
    {
        long long ans=1,base=x;
        while (y)
        {
            if (y&1) ans=(ans*base)%mod;
            base=(base*base)%mod;
            y>>=1;
        }
        return ans;
    }
    int main()
    {
        scanf("%lld",&n);
        for (long long i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            cnt[a[i]]++;mx=max(mx,a[i]);
        }
        for (long long i=1;i<=mx;i++)
            for (long long j=1;j*i<=mx;j++)
                num[i]+=cnt[i*j];
        for (long long i=mx;i>=1;i--)
        {
            if (!num[i]) continue;
            g[i]=1;
            for (long long j=2*i;j<=mx;j+=i)
                g[i]=(g[i]-g[j]+mod-1)%(mod-1);
        }
        f[1]=f[2]=1;
        for (long long i=3;i<=mx;i++) f[i]=(f[i-1]+f[i-2])%mod;
        for (long long i=1;i<=mx;i++) ans=(ans*f_pow(f[i],g[i]))%mod;
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    [LintCode] Cosine Similarity 余弦公式
    Word 2010 给公式添加序号
    Xshell连接不上虚拟机的问题和解决办法
    关于 “VMware Workstation 不可恢复错误- (vcpu-0)”
    TortoiseGit客户端安装及使用(上传代码到git@osc
    Android Studio修改项目名和包名
    Android 环信(Android)设置头像和昵称的方法
    Android SharedPreferences存储map的方法
    Android 环信聊天头像昵称显示解决方案
    Android 判断当前Fragment是否可见(Visible)
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6413288.html
Copyright © 2020-2023  润新知