11.03 刷题笔记

11.03 刷题总结

最近效率越来越低

不对,是做题的数量变少了,但是质量还是挺高的

这两天一直在做数学题和容斥题

今天只有四+1道题,但是每一道都是经典,但是不是特别套路

但是今天特别窝囊,因为看到好几道特别难的概率就跑了......

Luogu P7485 「Stoi2031」枫

我有题解了:链接

Luogu P3791 普通数学题

这个其实挺难的,但是在\(jbb\)的指导下,变得异常简单,感谢!!!

所以这个其实是用了数位\(DP\)的思想,使前几位紧贴上界,这样后面的就随机了

最后乘上一个方案数就好了

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int mod=998244353;
int n,m,x,a,b,ans;
map<int,int> mp;
int d(int x){
    //cout<<x<<endl;
    if(x<0)return 0;
    if(mp.find(x)!=mp.end())return mp[x];
    int ret=0,l=1,r;
    for(;l<=x;l=r+1){
        r=x/(x/l);
        ret=(ret+(r-l+1)*(x/l)%mod)%mod;
    }
    return mp[x]=ret;
}
int bas[55];
signed main(){
    scanf("%lld%lld%lld",&n,&m,&x);n++;m++;
    pyt(i,51,0)bas[i]=bas[i+1]|(1ll<<i);
    fxt(i,0,50){
        if(!((n>>i)&1))continue;
        fxt(j,0,50){
            if(!((m>>j)&1))continue;
            int mx=max(i,j),mn=min(i,j);
            //cout<<i<<" "<<j<<" "<<mx<<endl;
            ans=(ans+(1ll<<mn)%mod*(d(((n^(1ll<<i)^m^(1ll<<j)^x)&bas[mx])+(1ll<<mx)-1)-d(((n^(1ll<<i)^m^(1ll<<j)^x)&bas[mx])-1)+mod)%mod)%mod;
        }
        //cout<<ans<<endl;
    }
    printf("%lld",ans);
}

Luogu P4640 [ BJWC2008 ] 王之财宝

所以这个容斥被我半个小时就切了,不对忘记多长时间了??..

直接插板法,最后组合数要加起来,就是杨辉三角一列相加可以直接算

加加减减就好了

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e5+4;
int n,t,m,mod,ans;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int b[20];
int jc[N],inv[N];
int w(int x,int y){
    if(x<y)return 0;
    return jc[x]*inv[y]%mod*inv[x-y]%mod;
}
int C(int x,int y){
    if(y==0)return 1;
    return C(x/mod,y/mod)*w(x%mod,y%mod)%mod;
}
int sum[1<<15],num[1<<15],who[1<<15];
signed main(){
    scanf("%lld%lld%lld%lld",&n,&t,&m,&mod);
    jc[0]=1;fxt(i,1,mod-1)jc[i]=jc[i-1]*i%mod;
    inv[0]=1;inv[mod-1]=ksm(jc[mod-1],mod-2);
    pyt(i,mod-2,1)inv[i]=inv[i+1]*(i+1)%mod;
    ans=C(m+n,n);
    fxt(i,1,t)scanf("%lld",&b[i]),who[1<<i-1]=b[i]+1;
    int U=(1<<t)-1;
    fxt(s,1,U){
        num[s]=num[s-(s&-s)]+1;
        sum[s]=sum[s-(s&-s)]+who[s&-s];
        if(sum[s]>=m)continue;
        if(num[s]&1)ans=(ans-C(m-sum[s]+n,n)+mod)%mod;
        else ans=(ans+C(m-sum[s]+n,n))%mod;
    }
    printf("%lld",ans);
}

CF1271D Portals

傻逼\(DP\),直接转移就完事了

越靠后出兵越好,复杂度直接\(\mathcal{O(n^2)}\)

code
#include<bits/stdc++.h>
using namespace std;
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int N=5005;
int n,m,k;
int a[N],b[N],c[N],bl[N];
vector<int> e[N];
int f[N][N],ans=-1;
bool com(int x,int y){return c[x]>c[y];}
signed main(){
    scanf("%d%d%d",&n,&m,&k);
    fxt(i,1,n)scanf("%d%d%d",&a[i],&b[i],&c[i]),bl[i]=i;
    fxt(i,1,m){
        int x,y;
        scanf("%d%d",&x,&y);
        if(x>bl[y])bl[y]=x;
    }
    fxt(i,1,n)e[bl[i]].push_back(i);
    fxt(i,1,n)sort(e[i].begin(),e[i].end(),com);
    memset(f,0x8f,sizeof(f));f[0][k]=0;
    int now=k;
    fxt(i,1,n){
        int sum=0,cnt=0;now+=b[i];
        fxt(j,a[i],now-b[i])f[i][j+b[i]]=max(f[i][j+b[i]],f[i-1][j]);
        for(int x:e[i]){
            sum+=c[x];cnt++;
            fxt(j,max(cnt-b[i],a[i]),now-b[i]){
                f[i][j+b[i]-cnt]=max(f[i][j+b[i]-cnt],f[i-1][j]+sum);
            }
        }
    }
    fxt(i,0,5000)ans=max(f[n][i],ans);
    printf("%d",ans);
}

CF980D Perfect Groups

说实话这个题是真的水,只是我对负数开根竟然不给我报错!!!

去除一个数中的所有平方因子,这样只有两个数相同的时候才可以放到一组

当然还有\(0\)的情况,\(0\)可以任意放到一组中

直接用\(DP\)维护当前的数值个数就好了

对于每一个数记录他上一次出现的位置

code
#include<bits/stdc++.h>
using namespace std;
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int N=5005;
int n,a[N],ans[N];
int las[N],w;
map<int,int> pos;
int f[N];
signed main(){
    scanf("%d",&n);
    fxt(i,1,n){
        scanf("%d",&a[i]);
        if(a[i])fxt(j,2,sqrt(abs(a[i])))
            while(abs(a[i])%(j*j)==0)
                a[i]/=(j*j);
        las[i]=pos[a[i]];
        pos[a[i]]=i;
    }
    fxt(i,1,n){
        if(!a[i])w=i;
        fxt(j,1,i){
            if(las[i]<j)f[j]++;
            if(j<=w&&f[j]>1)ans[f[j]-1]++;
            else ans[f[j]]++;
        }
    }
    fxt(i,1,n)printf("%d ",ans[i]);
}
posted @ 2021-11-03 21:37  fengwu2005  阅读(69)  评论(0)    收藏  举报