noip模拟12
T1
和昨天一样,处理出一个大小较小的区间的问题,logn求答案。对于重复的\(i\)特判求解即可。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
typedef long long ll;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=3e5+100,M=1e6+100;std::vector<int>v[M];
int a[N],n,mod;
struct dd{int od,v;}st[N],pp;int l[N],r[N],top,ans,pre[N];
inline int get(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int teg(int x,int y){return x>y?x-y:(x==y?0:x-y+mod);}
inline void solve(int k,int L,int R,bool opt){
//pi(k);pi(L);pi(R);pi(opt);pn();
if(opt){
F(i,L,R){
int t=get(pre[i-1],a[k]);//pi(t);pn();
int x=lower_bound(v[t].begin(),v[t].end(),k)-v[t].begin();
int y=upper_bound(v[t].begin(),v[t].end(),r[k])-v[t].begin();
//pi(x),pi(y);pn();
ans+=y-x;
}if(get(pre[k-1],a[k])==pre[k])--ans;
}else{
F(i,L,R){
int t=teg(pre[i],a[k]);//pi(t);pn();
int x=lower_bound(v[t].begin(),v[t].end(),l[k]-1)-v[t].begin();
int y=upper_bound(v[t].begin(),v[t].end(),k-1)-v[t].begin();
//pi(x),pi(y);pn();
ans+=y-x;
}if(teg(pre[k],a[k])==pre[k-1])--ans;
}
}
inline short main(){
//file();
n=read();mod=read();
F(i,1,n){a[i]=read();pre[i]=(pre[i-1]+a[i])%mod;}
F(i,1,n){
pp.v=a[i],pp.od=i;l[i]=r[i]=i;
while(top&&st[top].v<a[i])r[st[top].od]=i-1,l[i]=l[st[top].od],top--;
st[++top]=pp;
}while(top)r[st[top].od]=n,top--;F(i,1,n)a[i]%=mod;
v[0].push_back(0);
F(i,1,n)v[pre[i]].push_back(i);//,pi(pre[i]);pn();
F(i,1,n){
if(l[i]!=r[i]){
if(i-l[i]<=r[i]-i)solve(i,l[i],i,1);
else solve(i,i,r[i],0);
}
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
T2
当m<mod时,暴力分子分母取膜,分母减分子求答案。
否则,分子是0,用蓝书上说的\(n!\)内\(P\)的个数为
\(\sum_{i=1}^{i<=log_p^n}n/p^i\)(向下取整)
于是约分求逆元即可。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register long long i=a;i>=b;i--)
typedef long long ll;
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
ll n,m,bin[65],cnt,B=1;const int mod=1e6+3;
inline ll ksm(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}return ans;
}
inline int fen(ll x){
int cnt=0;
B=B*(ksm(2,n)-x+mod)%mod;
while(!(x%2))x/=2,++cnt;
return cnt;
}
inline short main(){
n=read(),m=read();bin[0]=1;
F(i,1,63)bin[i]=bin[i-1]<<1;
if(m>mod){
ll cnt=0;
F(i,1,63)if(m-1>=bin[i])cnt+=(m-1)/bin[i];else break;
ll ans=ksm(2,n);ans=ksm(ans,m-1);
ll inv=ksm(2,cnt);inv=ksm(inv,mod-2);
ans=ans*inv%mod;
pi(ans);pi(ans);return 0;
}
ll ans=ksm(2,n);ans=ksm(ans,m-1);
ll inv=0;F(i,1,m-1)inv+=fen(i);
inv=ksm(2,inv);inv=ksm(inv,mod-2);
ans=ans*inv%mod;B=B*inv%mod;
pi((ans-B+mod)%mod);pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
T3
调了一下午,不亏!
up数组用来求最大值,down数组用来挡刀,只管up大,down合法即可。
求得最大值后直接dfs求方案,不知道为什么不会T,欢迎来hack~
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
typedef long long ll;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=2e5+100;int a[N],s[N],n,rec[N],cnt;
struct node{int val,len;}up[N],down[N];
inline void dfs(int k){
//pf("k : %d k+1 : %d a[k+1] : %d s[a[k+1]] : %d rec[k+1] : %d\n",k,k+1,a[k+1],s[a[k+1]],rec[k+1]);
if(a[k+1]<1||s[a[k+1]]>5)return;
if(k<=0){if(a[2]!=1)return;F(i,1,n)pi(rec[i]);exit(0);}
if(a[k]){if(a[k]!=a[k+1]-1&&a[k]!=a[k+1])return;if(s[a[k+1]]==1&&a[k+1]!=a[k])return;s[a[k]]++;if(s[a[k]]>5){s[a[k]]--;return;}rec[k]=a[k],dfs(k-1);s[a[k]]--;}
else{
if(s[a[k+1]]==1)a[k]=a[k+1],s[a[k]]++,rec[k]=a[k],dfs(k-1),s[a[k]]--,a[k]=0;
else if(s[a[k+1]]==5)a[k]=a[k+1]-1,s[a[k]]++,rec[k]=a[k],dfs(k-1),s[a[k]]--,a[k]=0;
else{
a[k]=a[k+1]; s[a[k]]++,rec[k]=a[k],dfs(k-1);s[a[k]]--;
a[k]=a[k+1]-1;s[a[k]]++;rec[k]=a[k];dfs(k-1);s[a[k]]--;a[k]=0;
}
}
}
int main(){
file();
n=read();F(i,1,n)a[i]=read();a[1]=1;
up[1].val=up[1].len=down[1].val=down[1].len=1;
F(i,1,n-1)if(a[i]&&a[i+1]&&a[i+1]<a[i]){pi(-1);return 0;}
if(a[n]&&a[n-1]&&a[n-1]!=a[n]){pi(-1);return 0;}
F(i,2,n){
if(a[i]){
if(up[i-1].val<a[i]&&up[i-1].len<2){pi(-1);return 0;}
if(down[i-1].val>a[i]){pi(-1);return 0;}
if(down[i-1].val==a[i]&&down[i-1].len==5){pi(-1);return 0;}
if(up[i-1].val<a[i]-1){pi(-1);return 0;}
if(up[i-1].val<a[i]||up[i-1].val>a[i])up[i].val=a[i],up[i].len=(a[i-1]?1:2);
if(up[i-1].val==a[i])up[i].val=a[i],up[i].len=up[i-1].len+1;
if(down[i-1].val==a[i])down[i].val=down[i-1].val,down[i].len=down[i-1].len+1;
if(down[i-1].val<a[i])down[i].val=a[i],down[i].len=1;
}
else{
if(up[i-1].len==1)up[i].val=up[i-1].val,up[i].len=2;
else up[i].val=up[i-1].val+1,up[i].len=1;
if(down[i-1].len==5)down[i].val=down[i-1].val+1,down[i].len=1;
else down[i].val=down[i-1].val,down[i].len=down[i-1].len+1;
}
}
pi(up[n].len>=2?up[n].val:up[n].val-1);pn();a[n]=rec[n]=up[n].len>=2?up[n].val:up[n].val-1;s[a[n]]=1;
dfs(n-1);
return 0;
}
Everything that kills me makes me feel alive.