1. 程式人生 > 其它 >多校衝刺 noip 11.04

多校衝刺 noip 11.04

多校衝刺 noip 11.04

今天掛大分!!我不嘚。。。

所以我啥時候可以把情況考慮完全啊!!

啥時候可以隨出來把我程式卡掉的資料啊!!

T1 謎之階乘

這題隨便做就能切,真的隨便做......

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e6+5;
int T,n,mx=1e18;
int cx[22][N],dy[22][N];
int cnt[23],c,ans[30][2];
signed main(){
    freopen("factorial.in","r",stdin);
    freopen("factorial.out","w",stdout);
    // cout<<(sizeof(cx)*3>>20)<<endl;
    fo(i,4,1000001){
        int now=i*(i-1);
        fu(j,i-2,2){
            if(now>mx/j)break;
            now*=j;
            cx[i-j+1][++cnt[i-j+1]]=now;
            dy[i-j+1][cnt[i-j+1]]=i;
        }
    }
    scanf("%lld",&T);
    while(T--){
        scanf("%lld",&n);
        if(n==1){printf("-1\n");continue;}
        c=1;ans[1][0]=n;ans[1][1]=n-1;
        int sq=sqrt(n);if(n!=2&&sq*(sq+1)==n)ans[++c][0]=sq+1,ans[c][1]=sq-1;
        fo(i,3,20){
            int pos=lower_bound(cx[i]+1,cx[i]+cnt[i]+1,n)-cx[i];
            if(cx[i][pos]==n)ans[++c][0]=dy[i][pos],ans[c][1]=dy[i][pos]-i;
        }
        printf("%lld\n",c);
        fu(i,c,1)printf("%lld %lld\n",ans[i][0],ans[i][1]);
    }
    return 0;
}

T2 子集

這個我找的規律好像不太好形容,所以看程式碼吧

考場上因為不會用官方給的\(checker\),於是自己寫了一個.....

checker
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e6+5;
int T,n,k;
int vis[N];
signed main(){
    FILE *f1=fopen("subset.in","r");
    FILE *f2=fopen("subset.out","r");
    FILE *f3=fopen("b.ans","w");
    fscanf(f1,"%lld",&T);
    fo(t,1,T){
        fscanf(f1,"%lld%lld",&n,&k);
        fo(i,1,n)vis[i]=false;
        char s[10];fscanf(f2,"%s",s+1);
        if(s[1]=='N')continue;
        fo(i,1,k){
            int sum=0;
            fo(j,1,n/k){
                int x;fscanf(f2,"%lld",&x);
                if(vis[x]||x>n){fprintf(f3,"WA on test %lld ",t);return 0;}
                sum+=x;vis[x]=true;
            }
            if(sum!=(n*(n+1))/2/k){fprintf(f3,"WA on test %lld ",t);return 0;}
        }
    }
    fprintf(f3,"AC");
    return 0;
}
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e6+5;
int T,n,k;
int odd[N][3];
void get_odd(int x){
    int mx=x*3;
    odd[1][0]=1;
    odd[1][1]=(mx>>1)+1;
    odd[1][2]=mx;
    fo(i,2,x){
        if(odd[i-1][1]+1==odd[i-1][2]){
            odd[i][0]=odd[i-1][0]+1;
            odd[i][1]=(((mx>>1)-i+1)>>1)+odd[i][0];
            odd[i][2]=mx-1;
            continue;
        }
        odd[i][0]=odd[i-1][0]+1;
        odd[i][1]=odd[i-1][1]+1;
        odd[i][2]=odd[i-1][2]-2;
    }
}
signed main(){
    freopen("subset.in","r",stdin);
    freopen("subset.out","w",stdout);
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld",&n,&k);
        if(n==1&&k==1){printf("Yes\n1\n");continue;}
        int sum=n*(n+1)/2,num;
        if(sum%k!=0||sum/k<n){printf("No\n");continue;}
        printf("Yes\n");num=n/k;
        if(num&1){
            get_odd(k);
            int s=k*3+1,t=n;
            fo(i,1,k){
                printf("%lld %lld %lld ",odd[i][0],odd[i][1],odd[i][2]);
                fo(i,4,num){
                    if(i&1)printf("%lld ",s),s++;
                    else printf("%lld ",t),t--;
                }
                printf("\n");
            }
        }
        else {
            int s=1,t=n;
            fo(i,1,k){
                fo(i,1,num){
                    if(i&1)printf("%lld ",s),s++;
                    else printf("%lld ",t),t--;
                }
                printf("\n");
            }
        }
    }
    return 0;
}

T3 混凝土粉末

這個題應該是個套路吧,只是我沒有見過,然後智商有點低,就沒有想出來

首先我們知道,如果某一次放沙子對某一次詢問有貢獻

我們需要保證兩個條件:

第一個是空間上,修改必須覆蓋詢問

第二個是時間上,修改必須在詢問前面

我們發現這個題意可以轉化為,詢問\(x\)位置上高度大於\(y\)的最早時間

這樣轉化完之後,很容易發現可以用二分,但是需要下面的維護

發現二分需要區間可加性,但是我們所說的空間是區間不可加的

所以我們掃描空間,用線段樹維護時間

我們對於每一個詢問,在基岩軸的左端點加上高度,右端點減去高度

每一個詢問,我們也可以將它放到基岩軸上去,可以直接線上段樹上二分

線段樹維護的是時間軸

我們直接掃描這個基岩軸

遇到需要加的就線上段樹上對應的時間處加上,減去一樣

查詢直接在詢問的時間左邊二分就好了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e6+5;
int n,q;
struct XDS{
    #define ls x<<1
    #define rs x<<1|1
    int sum[N*4],res,mx;
    void pushup(int x){
        sum[x]=sum[ls]+sum[rs];
        return ;
    }
    void ins(int x,int l,int r,int pos,int v){
        if(l==r)return sum[x]+=v,void();
        int mid=l+r>>1;
        if(pos<=mid)ins(ls,l,mid,pos,v);
        else ins(rs,mid+1,r,pos,v);
        pushup(x);return ;
    }
    void query(int x,int l,int r,int qr){
        if(~res||l>qr)return ;
        if(r<=qr){
            if(l==r){
                if(sum[x]>=mx)res=l;
                else mx-=sum[x];
                return ;
            }
            int mid=l+r>>1;
            if(sum[ls]<mx)mx-=sum[ls],query(rs,mid+1,r,qr);
            else query(ls,l,mid,qr);
            return ;
        }
        int mid=l+r>>1;
        query(ls,l,mid,qr);
        query(rs,mid+1,r,qr);
        return ;
    }
    #undef ls
    #undef rs
}xds;
vector<pair<int,int> > add[N],del[N],qry[N];
int ans[N];
signed main(){
    freopen("concrete.in","r",stdin);
    freopen("concrete.out","w",stdout);
    scanf("%lld%lld",&n,&q);
    for(int i=1,tp,l,r,h;i<=q;i++){
        scanf("%lld%lld%lld",&tp,&l,&r);
        if(tp==1){ans[i]=-1;
            scanf("%lld",&h);
            add[l].push_back(make_pair(h,i));
            del[r+1].push_back(make_pair(h,i));
        }
        else {
            qry[l].push_back(make_pair(r,i));
        }
    }
    fo(i,1,n){
        for(auto j:add[i])xds.ins(1,1,q,j.second,j.first);
        for(auto j:del[i])xds.ins(1,1,q,j.second,-j.first);
        for(auto j:qry[i]){
            xds.res=-1;xds.mx=j.first;
            xds.query(1,1,q,j.second);
            ans[j.second]=xds.res==-1?0:xds.res;
        }
    }
    fo(i,1,q)if(ans[i]!=-1)printf("%lld\n",ans[i]);
}

T4 排水系統

考場上幹傻了,沒看見只有一條壞了,直接轉移還有\(36pts\)

所以我們可以維護出來每一個位置的期望變化值

因為只有一條邊是壞掉的,所以我們就可以先按照沒有變化的推一遍

這時候求出來每一個點的變化值

再推一遍,將變化值下放

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=2e5+5;
const int M=5e5+5;
const int mod=998244353;
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 n,m,r,k;
int to[M],nxt[M],a[M],head[N],rp;
void add_edg(int x,int y,int z){
    to[++rp]=y;
    a[rp]=z;
    nxt[rp]=head[x];
    head[x]=rp;
}
int sum[N],cd[N],rd[N],du[N],all,inv;
int dp[N];
queue<int> q;
signed main(){
    freopen("water.in","r",stdin);
    freopen("water.out","w",stdout);
    scanf("%lld%lld%lld%lld",&n,&m,&r,&k);
    fo(i,1,k){
        int x,y,z;scanf("%lld%lld%lld",&x,&y,&z);
        add_edg(x,y,z);all=(all+z)%mod;
        cd[x]++;rd[y]++;du[y]++;
    }
    inv=ksm(all,mod-2);
    fo(i,1,m){sum[i]=dp[i]=1;q.push(i);}
    while(!q.empty()){
        int x=q.front();q.pop();
        dp[x]=(dp[x]-sum[x]+mod)%mod;
        int no=0,ys=0;
        for(int i=head[x];i;i=nxt[i]){
            int y=to[i];
            int now=sum[x]*ksm(cd[x]-1,mod-2)%mod*a[i]%mod*inv%mod;
            ys=(ys+now)%mod;no=(no+a[i])%mod;
            dp[y]=(dp[y]-now+mod)%mod;
        }
        no=(all-no+mod)%mod*inv%mod;
        ys=(ys+no*sum[x]%mod*ksm(cd[x],mod-2)%mod)%mod;
        for(int i=head[x];i;i=nxt[i]){
            int y=to[i];rd[y]--;
            dp[y]=(dp[y]+ys)%mod;
            sum[y]=(sum[y]+sum[x]*ksm(cd[x],mod-2))%mod;
            if(!rd[y])q.push(y);
        }
    }
    //fo(i,1,n)cout<<sum[i]<<" "<<dp[i]<<endl;
    fo(i,1,m)q.push(i);
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=nxt[i]){
            int y=to[i];du[y]--;
            dp[y]=(dp[y]+dp[x]*ksm(cd[x],mod-2))%mod;
            if(!du[y])q.push(y);
        }
    }
    //fo(i,1,n)cout<<sum[i]<<" "<<dp[i]<<endl;
    fo(i,n-r+1,n)printf("%lld ",(dp[i]+sum[i])%mod);
    return 0;
}