多校衝刺 noip 11.04
阿新 • • 發佈:2021-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;
}