CSP模拟19

CSP模拟19

T1 十年之约 CF1542C

我们要求

\[\sum_{i=1}^{n}f(i) \]

其中 $$f(i)=k\Leftrightarrow\operatorname{lcm}(1,2,3,\dots,k-1)\mid{i},k\nmid{i}$$
我们先预处理 $$an_i=\operatorname{lcm}(1,2,3,\dots,i)$$
所以对于 \(i=1,2,3,\dots,n\),满足 \(an_{k-1}\mid{i}\) 的有 \(\left\lfloor\dfrac{i}{an_{k-1}}\right\rfloor\) 个,满足 \(an_k\mid{i}\) 的有 \(\left\lfloor\dfrac{i}{an_k}\right\rfloor\) 个。

利用容斥原理,满足 \(an_{k-1}\mid{i},an_{k}\nmid{i}\) 的有 \(\left\lfloor\dfrac{i}{an_{k-1}}\right\rfloor-\left\lfloor\dfrac{i}{an_k}\right\rfloor\)
个。

这样,答案就是

\[\sum_{i=1}^{n}f_i=\sum_{an_i\le{n}}i\times\left(\left\lfloor\dfrac{i}{an_{k-1}} \right\rfloor-\left\lfloor\dfrac{i}{an_k}\right\rfloor\right)\]

由于 \(\operatorname{lcm}\) 增长很快,所以查询是 \(O(log n)\) 的。

code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long
int an[110],n,mod=1e9+7;
int lcm(int x,int y){
    return x*y/__gcd(x,y);
}
signed main(){
    an[0]=an[1]=1;
    for(int i=2;i<=100;i++){
        an[i]=lcm(an[i-1],i);
    }
    int t;
    scanf("%lld",&t);
    for(int i=1;i<=t;i++){
        scanf("%lld",&n);
        int ans=0;
        for(int j=1;an[j]<=n;j++){
            ans+=(j+1)*((n/an[j])-(n/an[j+1]))%mod;
            ans%=mod;
        }
        printf("%lld\n",ans);
    }
}

T2 可爱三小只 CF446B

直接贪心,用两个优先队列存储每行/列的和,取出最大的,减去代价后再放回,最后减去重复的部分即可。减去后可以是负数。

code

#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
#define int long long
int n,m,k,p,ph[1000010],pl[1000010];
int a[1010][1010],ans=-1e17;
priority_queue<int>qh,ql;
signed main(){
    scanf("%lld%lld%lld%lld",&n,&m,&k,&p);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%lld",&a[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        int sum=0;
        for(int j=1;j<=m;j++){
            sum+=a[i][j];
        }
        qh.push(sum);
    }
    for(int j=1;j<=m;j++){
        int sum=0;
        for(int i=1;i<=n;i++){
            sum+=a[i][j];
        }
        ql.push(sum);
    }
    for(int i=1;i<=k;i++){
        int x=qh.top();
        qh.pop();
        ph[i]=ph[i-1]+x;
        x-=m*p;
        qh.push(x);
    }
    for(int i=1;i<=k;i++){
        int x=ql.top();
        ql.pop();
        pl[i]=pl[i-1]+x;
        x-=n*p;
        ql.push(x);
    }
    for(int i=0;i<=k;i++){
        ans=max(ans,ph[i]+pl[k-i]-p*(k-i)*i);
    }
    printf("%lld",ans);
    return 0;
}

T3 蛋糕塌了

T4 西安行

code

#include<iostream>
#include<cstdio>
using namespace std;
#define int long long
const int mod=1e9+7;
int n,m,sta;
struct nod{
    int k[10][10];
    nod(){}
    int * operator [] (int i){
        return k[i];
    }
    nod(int x){
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i==j)
                k[i][j]=x;
                else k[i][j]=0;
            }
        }
    }
    friend nod operator * (nod x,nod y){
        nod c(0);
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                for(int l=0;l<3;l++){
                    c[i][j]=(c[i][j]+1ll*x[i][l]*y[l][j])%mod;
                }
            }
        }
        return c;
    }
}a,b,ans(1);
signed main(){
    scanf("%lld%lld",&n,&m);
    a[0][0]=2;a[0][1]=1;a[0][2]=1;
    a[1][0]=2;a[1][1]=1;a[1][2]=0;
    a[2][0]=1;a[2][1]=1;a[2][2]=1;
    b[0][0]=1;b[0][1]=0;b[0][2]=0;
    b[1][0]=2;b[1][1]=1;b[1][2]=0;
    b[2][0]=1;b[2][1]=1;b[2][2]=1;
    for(int i=1;i<=m;i++){
        int x;
        scanf("%lld",&x);
        int id=x-sta-1;
        nod c=a;
        while(id){
            if(id&1) ans=c*ans;
            c=c*c;
            id>>=1;
        }
        ans=b*ans;
        sta=x;
    }
    int id=n-sta-1;
    nod c=a;
    while(id){
        if(id&1) ans=c*ans;
        c=c*c;
        id>>=1;
    }
    ans=b*ans;
    printf("%lld\n",ans[2][0]);
    return 0;
}
posted @ 2023-08-13 07:20  muzqingt  阅读(13)  评论(0编辑  收藏  举报