CCPC Wannafly Camp Day1C染色图

题:https://ac.nowcoder.com/acm/contest/3979/C

题意:给定一个函数g(n,k),指的是n个点的图,每个点可染k种颜色中的一种,只有不同颜色之间才可以进行连边,求能达到的最大连边数。题目要求的是Σg(n,i)

分析:考虑单单的一个点k,考虑答案:C2n-p(总体-不满足=答案),而p函数显然就是相同颜色之间可连的边的数目,为了答案尽可能大,我们要让p函数尽可能小,即让相同颜色的点数的个数尽可能接近;

   具体地就是n%k种颜色染了n/k个点,k-n%k种颜色染了n/k+1个点。

   此时g(n,k)=C2n-(n%k)*Cx+12-(k-n%k)*Cx2   (其中x=n/k)

   将n%k==n-n/k*k带入得g(n,k)=n2-n-2nx+k(x2+x)

   而求和就考虑用分块解决(因为有x=n/k)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int M=5e4+4;
const int mod=998244353;
ll ksm(ll a,ll b){
    ll t=1;
    while(b){
        if(b&1)
            t=(t*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return t;
}
ll solve(ll x,ll y,ll n){
    ll ans=0;
    ll l=x,r;
    while(l<=y){
     ///   cout<<l<<endl;
        r=n/(n/l);
        if(r>y)
            r=y;
        ll t=n/l;
        ans+=(n*n%mod-n-2*n%mod*t)%mod*(r-l+1)%mod;
        ans%=mod;
                                ///等差求和///
        ans+=(((t*t%mod+t)%mod)*((r+l)*(r-l+1)/2)%mod)%mod;
        ans%=mod;
        l=r+1;
    }
    return ans;
}
int main(){
    int t;
    scanf("%d",&t);
    ll inv=ksm(2ll,mod-2);
    while(t--){
        ll l,r,n;
        scanf("%lld%lld%lld",&n,&l,&r);
        ll ans=solve(l,r,n);
        ans=(ans+mod)%mod;
        ans*=inv;
        printf("%lld\n",ans%mod);
    }
    return 0;
}
View Code

 

posted @ 2020-05-05 14:37  starve_to_death  阅读(152)  评论(0编辑  收藏  举报