CCPC-Wannafly Winter Camp Day3 (Div2, onsite)

F:

/*
根据上面的推导就变成了最后一个式子
暴力能过(加一些乱七八糟的东西) 
因为n/i的结果是 类似 n n-1 n-1 n-2 n-2 n-2 n-3 n-3 n-3....
的东西(好像是有logn种),所以稍微存一下已经处理过得答案 
然后在根据1e7之内莫比乌斯函数不为零的 只有3e6个大约 
1300ms 
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 10000010
#define ll long long
#define mod 998244353
using namespace std;
int n,mu[maxn],f[maxn],prime[maxn/10],num;
int k[maxn],m;
ll ans,vis[maxn];
void Mbs(){
    mu[1]=1;
    for(int i=2;i<=10000000;i++){
        if(f[i]==0){
            prime[++num]=i;mu[i]=-1;
        }
        for(int j=1;j<=num;j++){
            if(prime[j]*i>10000000)break;
            f[prime[j]*i]=1;
            if(i%prime[j]==0){
                mu[prime[j]*i]=0;break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
    for(int i=1;i<=10000000;i++)
        if(mu[i]!=0)k[++m]=i;
}
ll Cal(int x){
    if(vis[x])return vis[x];
    ll res=0,d;
    for(int i=1;i<=m;i++){
        if(k[i]>x)break;
        d=k[i];if(x/d==0)break;
        res=((res+mu[d]*(x/d)*(x/d)%mod)%mod+mod)%mod;
    }
    vis[x]=res;
    return res;
}
int main(){
    scanf("%lld",&n);Mbs();
    for(int i=1;i<=m;i++){
        if(k[i]>n)break;
        int x=k[i];
        ans=((ans+mu[x]*Cal(n/x)%mod)%mod+mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

/*
太慢了
上面的结论,其实不用存下来 
我们想要的是对于ij n/i==n/j
能不能只算一次
可以的
观察最后的式子
发现Cal返回的值是一样的,只有mu不一样
那就维护mu的前缀和
一段一段的求
就快起来了
300+ms 
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 10000010
#define ll long long
#define mod 998244353
using namespace std;
ll n,mu[maxn],f[maxn],prime[maxn/10],num,ans;
void Mbs(){
    mu[1]=1;
    for(ll i=2;i<=10000000;i++){
        if(f[i]==0){
            prime[++num]=i;mu[i]=-1;
        }
        for(ll j=1;j<=num;j++){
            if(prime[j]*i>10000000)break;
            f[prime[j]*i]=1;
            if(i%prime[j]==0){
                mu[prime[j]*i]=0;break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
    for(ll i=1;i<=10000000;i++)
        mu[i]+=mu[i-1];
}
ll Cal(ll x){
    ll res=0;
    for(ll i=1,j;i<=x;i=j+1){
        j=x/(x/i);
        res=((res+(mu[j]-mu[i-1])*(x/i)*(x/i)%mod)%mod+mod)%mod;
    }
    return res;
}
int main(){
    scanf("%lld",&n);Mbs();
    for(ll i=1,j;i<=n;i=j+1){
        j=n/(n/i);
        ans=((ans+(mu[j]-mu[i-1])*Cal(n/i)%mod)%mod+mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

H:

/*
介于每个点之间没有影响 我们可以求出每个点是黑的期望
然后还差q步的涂白
用二维bit搞搞就好了 
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 1010
#define ll long long
#define mod 998244353
using namespace std;
ll n,m,q,g[maxn][maxn],a[maxn][maxn],ans;
ll qc(ll a,ll b){
    ll res=1;while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod;b>>=1;
    }
    return res;
}
void Insert(ll x,ll y,ll z){
    for(ll i=x;i<=n;i+=i&(-i))
        for(ll j=y;j<=m;j+=j&(-j))
            a[i][j]+=z;
}
ll Query(ll x,ll y){
    ll res=0;
    for(ll i=x;i>0;i-=i&(-i))
        for(ll j=y;j>0;j-=j&(-j))
            res+=a[i][j];
    return res;
}
int main(){
    scanf("%lld%lld%lld",&n,&m,&q);
    ll l,r,sum;
    for(ll i=1;i<=n;i++){
        scanf("%lld%lld",&l,&r);
        sum=(r-l+1)*(r-l+2)/2;
        for(ll j=l;j<=r;j++)
            g[i][j]=(j-l+1)*(r-j+1)%mod*qc(sum,mod-2)%mod;
    }
    ll x1,x2,y1,y2;
    while(q--){
        scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
        Insert(x2+1,y2+1,-1);Insert(x1,y1,-1);
        Insert(x2+1,y1,1);Insert(x1,y2+1,1);
    }
    for(ll i=1;i<=n;i++)
        for(ll j=1;j<=m;j++)
            if(Query(i,j)>=0)ans=(ans+g[i][j])%mod;
    printf("%lld\n",ans);
    return 0;
}

I:

/*
带权并茶几 
假设我们有了每个人当前和A个人打过架
其中a次做主场,b次做客场
那么方案数为3^(n-A)*2^a
下面考虑处理出A a b 
y去打x这件事,x主场,y客场,
原来所有可能在y座位上的人,要想赢,则b++
原来所有可能在x座位上的人,想要赢,则a++
大体上就是一个裸地带权并茶几,每次find的时候拿起路上的ab值
但是有个问题就是 y连到了x上,那么y的孩子们find的时候会把x的 ab值加上
显然不对
每次合并,虚拟出来一个点,xy都连向它,它的ab值为零
然后就好了 
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 800010
#define ll long long
#define mod 998244353
using namespace std;
ll n,m,fa[maxn],a[maxn],b[maxn];
struct node{
    ll a,b,fa;
};
ll find(ll x){
    if(x==fa[x])return x;
    ll fat=fa[x];
    fa[x]=find(fa[x]);
    a[x]+=a[fat];
    b[x]+=b[fat];
    return fa[x];
}
ll Qc(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1)res=res*a%mod;
        b>>=1;a=a*a%mod;
    }
    return res;
}
ll Cal(ll x){
    find(x);ll A=a[x]+b[x];
    ll ans=Qc(3,n-A);
    ans=ans*Qc(2,a[x])%mod;
    return ans;
}
int main(){
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n*4;i++)fa[i]=i;
    ll c,x,y,now=n;
    for(ll i=1;i<=m;i++){
        scanf("%lld",&c);
        if(c==1){
            scanf("%lld%lld",&x,&y);
            ll fx=find(x);ll fy=find(y);
            a[fx]++;b[fy]++;fa[fx]=++now;fa[fy]=now;
        }
        else {
            scanf("%lld",&x);printf("%lld\n",Cal(x));
        }
    }
}

 

posted @ 2019-02-28 22:24  一入OI深似海  阅读(170)  评论(0编辑  收藏  举报