2017-10-4 清北刷题冲刺班a.m
P101
zhx
a
【问题描述】
你是能看到第一题的 friends 呢。
——hja
Hja 拥有一套时光穿梭技术,能把字符串以超越光速的速度传播,但是唯一
的问题是可能会 GG。在传输的过程中,可能有四种情况:
1、字符串没有发生改变。
2、字符串的某一位由 0 变 1 或者由 1 变 0。
3、某一位消失了。
4、多了一位。
为了防止字符串 GG,Hja 保证发送的字符串只由 01 组成,并且所有字符
串开始的长度均为?,并且所有为 1 的位置的下标之和一定是? + 1的倍数。在
给定了你这些条件之后,Hja 告诉你传输之后的字符串,并按照以下规则复原
字符串:
1、对于一个字符串,按照四种规则从前到后的优先级依次尝试能否复原为
一个合法的字符串。
2、对于同一种操作,更靠前的位置更加优先。
3、对于同一种操作的同一位置,0 比 1 更加优先。
4、如果没有任何一种方法复原字符串,则输出−1。
【输入格式】
第一行一个整数?,代表所有字符串的长度。
接下来若干行,每行一个字符串。
【输出格式】
对于每个字符串,输出一行代表答案。
【样例输入】
4
0000
011
1011
11011
【样例输出】
0000
0110
1001
1111
【数据范围与规定】
对于100%的数据,4 ≤ ? ≤ 1000,字符串数量不超过3000。
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100000 using namespace std; int mod,pos[maxn],cnt,del[maxn],w[maxn],sum[maxn]; string s; bool f; int n,len,l; void dfs(int len,int Sum,int t){ if(f)return; if(len==n&&Sum%mod==0){ for(int i=0;i<l;i++){ if(del[i])continue; printf("%c",s[i]); } printf("\n"); f=1; return; }if(t)return; if(len==n)return; for(int i=0;i<l;i++){ if(!del[i]){ del[i]=1; if(s[i]=='0'){ dfs(len-1,Sum-w[i],1);if(f)return; } if(s[i]=='1'){ dfs(len-1,Sum-(i+1)-w[i+1],1);if(f)return; } del[i]=0; } } } void dfs1(int c,int Sum,int t){ if(f)return; if(Sum%mod==0){ cout<<s<<endl; f=1; return; }if(t)return; if(c==0)return; for(int i=1;i<=cnt;i++){ if(!del[pos[i]-1]){ del[pos[i]-1]=1; s[pos[i]-1]='0'; dfs1(c-1,Sum-pos[i],1); del[pos[i]-1]=0; s[pos[i]-1]='1'; } } } int main(){ //freopen("Cola.txt","r",stdin); freopen("a.in","r",stdin);freopen("a.out","w",stdout); scanf("%d",&n); mod=n+1; while(cin>>s){ memset(del,0,sizeof(del)); memset(w,0,sizeof(w)); f=0; cnt=0; l=len=s.length(); int Sum=0; for(int i=0;i<len;i++) if(s[i]=='1'){ pos[++cnt]=i+1; Sum+=i+1; } for(int i=l-1;i>=0;i--){ if(s[i]=='1')w[i]=w[i+1]+1; else w[i]=w[i+1]; } if(len==n){//一定是1,2操作 if(Sum%mod==0){ cout<<s<<endl; continue; } bool flag=0; dfs1(cnt,Sum,0); if(!f) printf("-1\n"); continue; } if(len>n){//删掉几位 if(len-n>1){ printf("-1\n"); continue; } f=0; dfs(len,Sum,0); if(!f)printf("-1\n"); continue; } if(len<n){//加上几位 if(n-len>1){ printf("-1\n"); continue; } int num=0; for(int i=len-1;i>=0;i--){ if(s[i]=='1') num+=i+1; sum[i]=sum[i+1]+(s[i]=='1'?1:0); } int ans=num%(n+1),flag=0; for(int i=0;i<=len;i++){ if((sum[i]+ans)%(n+1)==0){ for(int j=0;j<len;j++) if(j!=i) cout<<s[j]; else if(i!=len) cout<<"0"<<s[j]; if(i==len) cout<<"0"; flag=1; break; } if((sum[i]+ans+i+1)%(n+1)==0){ for(int j=0;j<len;j++) if(j!=i) cout<<s[j]; else if(i!=len) cout<<"1"<<s[j]; if(i==len) cout<<"1"; flag=1; break; } } if(!flag) cout<<"-1"; printf("\n"); } } fclose(stdin);fclose(stdout); return 0; }
b
【问题描述】
你是能看到第二题的 friends 呢。
——laekov
Hja 和 Yjq 在玩游戏,这个游戏中 Hja 给了 Yjq 两个数?,?,希望 Yjq 找到
一些非负整数使得这些数的和等于?,并且所有数模?的值互不相同,求方案
数。
【输入格式】
一行两个整数?,?。
【输出格式】
一行一个整数代表答案对905229641取模之后的结果。
【样例输入 1】
3 3
【样例输出 1】
9
【样例输入 2】
523 44
【样例输出 2】
338398304
【数据范围与规定】
220,? ≤ 5。
4300,? ≤ 10。
70%的数据,? ≤ 10 18 ,? ≤ 20。
对于100%的数据,? ≤ 10 18 ,? ≤ 100。
#include<iostream> #include<cstdio> #define mod 905229641 using namespace std; long long n,limit,sm[500010]; int m,ans; void dfs(int yu,long long res,int use){ if(res==0){ ans=(ans+sm[use])%mod; return; } if(yu==m)return; if(res<0)return; dfs(yu+1,res,use); for(int i=0;i<=limit;i++) dfs(yu+1,res-(i*m+yu),use+1); } int main(){ //freopen("Cola.txt","r",stdin); freopen("b.in","r",stdin);freopen("b.out","w",stdout); sm[1]=1; for(int i=2;i<=500000;i++)sm[i]=sm[i-1]*i%mod; cin>>n>>m; limit=n/m; dfs(0,n,0); printf("%d",ans); fclose(stdin);fclose(stdout); return 0; }
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif const int maxn=110; const int maxs=maxn*maxn/2; const int mo=905229641; long long n; int m,f[maxn][maxs],fac[maxn]; int calc(long long a,long long b) { long long ans=1; for (int c=1;c<a;c++) ans=ans*(b+c)%mo; return (int)ans; } int main() { freopen("b.in","r",stdin); freopen("b.out","w",stdout); scanf(LL "%d",&n,&m); f[0][0]=1; int up=m*(m-1)/2; for (int a=0;a<m;a++) for (int b=m;b>=0;b--) for (int c=up;c>=0;c--) if (f[b][c]) f[b+1][c+a]=(f[b+1][c+a]+f[b][c])%mo; fac[0]=1; for (int a=1;a<=m;a++) fac[a]=(long long)fac[a-1]*a%mo; int x=(int)(n%m); int ans=0; for (int a=x;a<=n && a<=up;a+=m) { long long rest=(n-a)/m; for (int b=1;b<=m;b++) if (f[b][a]) { int nowans=calc(b,rest%mo); nowans=(long long)nowans*f[b][a]%mo; nowans=(long long)nowans*b%mo; ans=(ans+nowans)%mo; } } printf("%d\n",ans); return 0; }
c
【问题描述】
你是能看到第三题的 friends 呢。
——aoao
Hja 回到老家开始种地,由于太久没有种地,所以所有地都是荒地。将每片
地从荒地变成不荒地有一定的代价, 但是一旦改变之后就不再是荒地了。 现在Hja
要开始?年的种地生活,第?年 Hja 可以在? ? 到? ? 块地上种地,并且可以获得? ? 的
收益。 (注意,要种地必须整段一起种,并且这些地一定已经是不荒地)Hja 可以
选择种或者不种每一年的地,问 Hja 能够获得的最大收益。
【输入格式】
第一行两个整数?,?,代表地的数量和年数。
一行?个数,代表每块地变成不荒地的代价。
接下来?行,每行三个整数? ? ,? ? ,? ? 如题意描述。
【输出格式】
一行一个整数代表答案。
【样例输入】
7 4
3 2 3 2 1 2 3
1 2 5
2 3 5
3 5 3
7 7 5
【样例输出】
4
【数据规模与约定】
30%的数据,1 ≤ ?,? ≤ 100。
对于100%的数据,1 ≤ ?,? ≤ 100000。
#include<iostream> #include<cstdio> #define maxn 100010 using namespace std; int n,m,w[maxn],ans=0,a[maxn*2],cnt; struct node{ int l,r,v; }p[maxn]; void dfs(int now,int sum){ if(now==m+1){ ans=max(ans,sum); return; } dfs(now+1,sum); int due=0; int pos=cnt+1; for(int i=p[now].l;i<=p[now].r;i++)due+=w[i],a[++cnt]=w[i],w[i]=0; dfs(now+1,sum-due+p[now].v); for(int i=p[now].l,j=pos;i<=p[now].r;i++,j++)w[i]=a[j]; cnt=pos-1; } int main(){ //freopen("Cola.txt","r",stdin); freopen("c.in","r",stdin);freopen("c.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&w[i]); for(int i=1;i<=m;i++) scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].v); dfs(1,0); cout<<ans; fclose(stdin);fclose(stdout); return 0; }
#include <cstdio> #include <cctype> #include <memory.h> #include <algorithm> using namespace std; typedef long long qw; #ifdef WIN32 #define lld "%I64d" #else #define lld "%lld" #endif int nextInt() { int s = 0, d; bool nag = 0; do { d = getchar(); if (d == '-') nag = 1; } while (!isdigit(d)); do s = s * 10 + d - 48, d = getchar(); while (isdigit(d)); return nag ? -s : s; } struct seg { int l, r; qw v, z; seg *ls, *rs; }; struct obj { int l, r, v; }; inline bool cmpObj(const obj& a, const obj& b) { return (a. l < b. l) || (a. l == b. l && a. r < b. r); } const int maxn = 200009; const qw inf = 0x3f3f3f3f3f3f3f3fLL; int n, m; obj q[maxn]; qw s[maxn], ans; seg *rtf, *rtc, *sp; #define mid(p) ((p->l+p->r)>>1) seg *sgtBuild(int l, int r) { seg *p = sp ++; p-> v = - inf; p-> z = 0; p-> l = l; p-> r = r; if (l + 1 < r) { p-> ls = sgtBuild(l, mid(p)); p-> rs = sgtBuild(mid(p), r); } return p; } void sgtChg(seg* p, int p0, qw v0) { if (p-> l + 1 == p-> r) p-> v = max(p-> v, v0); else { if (p0 < mid(p)) sgtChg(p-> ls, p0, v0 - p-> z); else sgtChg(p-> rs, p0, v0 - p-> z); p-> v = max(p-> ls-> v, p-> rs-> v) + p-> z; } } qw sgtQry(seg* p, int l, int r) { if (l >= r) return -inf; else if (p-> l == l && p-> r == r) return p-> v; else if (r <= mid(p)) return sgtQry(p-> ls, l, r) + p-> z; else if (l >= mid(p)) return sgtQry(p-> rs, l, r) + p-> z; else return max(sgtQry(p-> ls, l, mid(p)), sgtQry(p-> rs, mid(p), r)) + p-> z; } void sgtLazy(seg* p, int l, qw z0) { if (p-> v == -inf) return; else if (p-> l == l) p-> v += z0, p-> z += z0; else { if (l < mid(p)) { sgtLazy(p-> ls, l, z0); sgtLazy(p-> rs, mid(p), z0); } else sgtLazy(p-> rs, l, z0); p-> v = max(p-> ls-> v, p-> rs-> v) + p-> z; } } int main() { freopen("c.in","r",stdin); freopen("c.out","w",stdout); sp = new seg[maxn * 6]; n = nextInt(); m = nextInt(); rtf = sgtBuild(0, n + 2); rtc = sgtBuild(0, n + 2); s[0] = 0; for (int i = 1; i <= n; i ++) s[i] = s[i - 1] + nextInt(); for (int i = 0; i < m; i ++) { q[i]. l = nextInt(); q[i]. r = nextInt(); q[i]. v = nextInt(); } sort(q, q + m, cmpObj); ans = 0; for (int i = 0; i < m; i ++) { qw res0 = max(sgtQry(rtf, 0, q[i]. l), 0LL) - s[q[i]. r] + s[q[i]. l - 1]; qw res1 = sgtQry(rtc, q[i]. l, q[i]. r + 1) - s[q[i]. r]; qw res = max(max(res0, res1), sgtQry(rtf, q[i]. r, n + 1)) + q[i]. v; sgtLazy(rtf, q[i]. r, q[i]. v); sgtLazy(rtc, q[i]. r, q[i]. v); sgtChg(rtf, q[i]. r, res); sgtChg(rtc, q[i]. r, res + s[q[i]. r]); ans = max(ans, res); } printf(lld "\n", ans); }