CCPC-Wannafly Winter Camp Day3 (Div2, onsite)

F:node

/*
根據上面的推導就變成了最後一個式子
暴力能過(加一些亂七八糟的東西) 
由於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:ios

/*
介於每一個點之間沒有影響 咱們能夠求出每一個點是黑的指望
而後還差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));
        }
    }
}
相關文章
相關標籤/搜索