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\n",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\n",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\n",ans);
    return 0;
}
时间: 2024-11-05 23:19:32

FR #12题解的相关文章

cojs 强连通图计数1-2 题解报告

OwO 题目含义都是一样的,只是数据范围扩大了 对于n<=7的问题,我们直接暴力搜索就可以了 对于n<=1000的问题,我们不难联想到<主旋律>这一道题 没错,只需要把方程改一改就可以了 首先我们考虑不合法的方案强连通分量缩点后一定是DAG 考虑子问题:DAG计数 做法可以参考<cojs DAG计数1-4 题解报告> 这里给出转移方程 f(n)=sigma((-1)^(k-1)*C(n,k)*2^(k*(n-k))*f(n-k)) 如果考虑上强连通分量缩点的情况呢? 我

[CCF2015.12]题解

201512-1 数位之和 水题一个,取模除以10胡搞即可(不知道字符串为什么不行 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <casser

2017 acm icpc 沈阳(网络赛)5/12 题解

比赛中较...能做的5道题 hdoj6195. cable cable cable 题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=6195 题目大意 : 略 规律 : 答案 = k+(m-k)*k hdoj6198. number number number 题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=6198 题目大意  : 给你一个整数n.问你n个斐波那契数(可重复)不能构成哪些数,输出

模拟12 题解

A. 斐波那契(fibonacci) 首先想到a,b<=1e6的暴力:建树,直接向上标记求lca. 建树的过程中发现一个性质. 斐波那契第n代兔子,是n-2代及以前的兔子的儿子. 因为编号连续且与父亲编号大小有关, 设该节点的编号为$x$,在第$k$代, 则$f(x)=x-fib(k-1)$. 二分查找父亲,向上标记求lca即可. (特判不换行,爆零两行泪) (见代码第25行) 1 #include<iostream> 2 #include<cstdio> 3 #define

2019.10.12题解

A. 木板 标签: 素因数的根号筛法 题解: 由相似三角形可得: $ ans=8*\sum_{i=1}^{n-1}[i*i(mod)n==0] $ 根号筛出质因子即可 B. 打扫卫生 标签: Dp+链表 正解: 暴力可A的一道题,但是正解其实并不难想 最暴力的Dp式子:$ f[i]=min{f[j]+cnt(j+1,i)^2} $ 假如j从i-1枚举,那么我们发现当cnt数到了sqrt(f[i])以上后对答案一定没有贡献 考虑用一个链表维护每个数截至到i出现的最后位置以保证复杂度$ O(nsqr

FR #10题解

好 蠢 啊 A. 标准分治.每次从分治区间中找到最大值的位置m,设f[l,r]为[l,r]的答案,那么f[l,r]=f[l,m-1]+f[m+1,r]+跨过m点的贡献. 然后枚举小的区间放到大的区间中查就行了.复杂度nlog^2n. TM的这5e5你给128M怎么回事...开6s又怎么回事... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define

FR #1题解

A. 建图跑最小费用最大流.分类讨论每种情况如何连边,费用怎么定. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxv 105 #define maxe 100500 #define inf 1000000000 using namespace std; int n,m,a[maxv],b[ma

FR #11题解

A. 瞎jb折半dp一下,然后合并一下就好了. O2加成十分显著...6s变成0.9s... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<bitset> #define maxv 100 #define maxe 20000 using namespace std; int n,m,d,x,y,z,g[maxv],nume=1

FR #2题解

A. 考虑把(u,v)的询问离线挂在u上,然后dfs,每次从fath[x]到[x]相当于x子树dis区间加1,x子树以外区间-1,然后维护区间和区间平方和等. 常数略大. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define maxv 100500 #define maxe 200500 using na