期望得分:0+40+30=70

实际得分:0+10+10=20

题目修改:只能由0变1,只能用一次操作

大模拟

#include<cstdio>
#include<cstring>
using namespace std;
char s[];
int len,n;
int cnt[];
bool solve1()
{
if(len!=n) return false;
int num=;
for(int i=;i<len;i++)
if(s[i]=='') num+=i+;
if(num%(n+)==)
{
puts(s);
return true;
}
return false;
}
bool solve2()
{
if(len!=n) return false;
int num=;
for(int i=;i<len;i++)
if(s[i]=='') num+=i+;
for(int i=;i<len;i++)
if(s[i]=='')
{
num-=(i+);
if(num%(n+)==)
{
for(int j=;j<i;j++) putchar(s[j]);
putchar('');
for(int j=i+;j<len;j++) putchar(s[j]);
printf("\n");
return true;
}
num+=(i+);
}
return false;
}
bool solve3()
{
if(len<=n) return false;
int num=;
for(int i=;i<len;i++)
if(s[i]=='') num+=i+,cnt[i+]=cnt[i]+;
else cnt[i+]=cnt[i];
for(int i=;i<len;i++)
if(s[i]=='')
{
num-=(cnt[len]-cnt[i]);
if(num%(n+)==)
{
for(int j=;j<i;j++) putchar(s[j]);
for(int j=i+;j<len;j++) putchar(s[j]);
printf("\n");
return true;
}
num+=(cnt[len]-cnt[i]);
}
else
{
num-=(cnt[len]-cnt[i+]);
num-=(i+);
if(num%(n+)==)
{
for(int j=;j<i;j++) putchar(s[j]);
for(int j=i+;j<len;j++) putchar(s[j]);
printf("\n");
return true;
}
num+=(cnt[len]-cnt[i+]);
num+=(i+);
}
return false;
}
bool solve4()
{
if(len>=n) return false;
int num=;
for(int i=;i<len;i++)
if(s[i]=='') num+=(i+),cnt[i+]=cnt[i]+;
else cnt[i+]=cnt[i];
for(int i=;i<len;i++)
{
num+=cnt[len]-cnt[i];
if(num%(n+)==)
{
for(int j=;j<i;j++) putchar(s[j]);
putchar('');
for(int j=i;j<len;j++) putchar (s[j]);
printf("\n");
return true;
}
num+=i+;
if(num%(n+)==)
{
for(int j=;j<i;j++) putchar(s[j]);
putchar('');
for(int j=i;j<len;j++) putchar(s[j]);
printf("\n");
return true;
}
num-=(i+);
num-=(cnt[len]-cnt[i]);
}
if(num%(n+)==) { printf("%s",s); printf("0\n");return true; }
if((num+len+)%(n+)==) { printf("%s",s); printf("1\n"); return true; }
return false;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
while(scanf("%s",s)!=EOF)
{
len=strlen(s);
if(solve1()) continue;
if(solve2()) continue;
if(solve3()) continue;
if(solve4()) continue;
printf("-1\n");
}
}

题目中要求选的数 %m 互不相同

那么可以很自然的想到

先在<m的数里选k个 ,使他们的和 s%m=n%m,那么还剩下n-s

为了保证%m 不相同,所以 我们把剩下的n-s 分为 (n-s)/m 个 m,

给这k个数分 m

也就是说

如果要换掉x,只能用和x 模m属于同一剩余系 的数换,所以 只能加 m的整数倍

设f[i][j] 表示选了i个数,和为j,且选的i个数互不相同的方案数

设g[i][j]表示把i个m分给j个数的方案数

那么ans= Σ f[i][j] * g[(n-j)/m][i] * i !,  其中要求j%m=n%m

这里要乘i的阶乘,因为 1 2 和 2 1 算作不同的方案

如何求f[i][j] ?

很容易想到 f[i][j][k] 表示 选了i个数,和为j,选的数字中最大的为k的方案数

这样是m^4,TLE

其实可以压去第三维

两维的缺陷是 如果顺序枚举i,枚举j,再枚举现在选哪个数,不能保证选的数%m互不相同

因为对于同一个数k,可能f[i+1][j] 由 已经选了k的f[i][j-k]再选k转移而来

解决的方法是

先枚举当前选哪个数,再倒序枚举选了多少个数,再枚举这些数的和

这样就保证了对于同一个数k,不会让 i+1 由 i 转移

如何求g[i][j]?

把i个东西分给j个人,显然是组合数

C(i+j-1,j-1)

难道 还要逆元?

其实不用 ,这个C 化开为:

1*2* …… i+j-1

---------------------------------(这是分数线)

(1*2……j-1)*(1*2……*i)

= ((i+1)*(i+2)……*(i+j-1))/((j-1)!)

不要漏了 统计答案的时候还要乘上j! 所以分母消去只剩下个j

求 (i+1)*(i+2)……*(i+j-1) 的时候,i 本身可能是 long long ,不要忘了先取模,防止 乘爆

#include<cstdio>

#define M 101

using namespace std;

typedef long long LL;

const LL mod=;

int f[M][M*M/];

LL mul(LL a,LL b)
{
LL res=;
for(LL i=a;i<=b;i++) res*=i,res%=mod;
return res;
} int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
LL n; int m;
scanf("%I64d%d",&n,&m);
int mx=m*(m-)/;
f[][]=;
for(int k=;k<m;k++)
for(int i=m;i;i--)
for(int j=k;j<=mx;j++)
f[i][j]+=f[i-][j-k],f[i][j]%=mod;
int x=n%m; LL res,ans=,y;
for(int i=x;i<=mx && i<=n;i+=m)
{
y=(n-i)/m;
for(int j=;j<=m;j++)
if(f[j][i])
{
res=mul((y+)%mod,(y+j-)%mod);
res*=f[j][i]; res%=mod;
res*=j; res%=mod;
ans+=res,ans%=mod;
}
}
printf("%I64d",ans);
}

解决本题的突破点:

哪一年种哪些地可以随意定

dp[i] 表示 种过的最右边的地为i时的最大收益

将所有的种地区间按左端点从左到右排序

那么对于当前这个种地区间[l[i],r[i]]

它的上一个种地区间 [l[j],r[j]],

l[j]一定<=l[i]

r[j]可能有三种情况

① r[j] < l[i] 此时第i块地 有全部的垦荒代价

② r[j]∈[l[i],r[i]) 此时第i块地 有 右边部分的垦荒代价

③ r[j]>=r[i] 此时第i块地 没有垦荒代价

令sum[i]表示垦荒代价的前缀和,val[i]表示第i次垦荒的收益

那么对应的状态转移方程:

① dp[r[i]]=max(dp[r[j]]+val[i]-(sum[r[i]]-sum[l[i]-1]))

② dp[r[i]]]=max(dp[r[j]]+val[i]-(sum[r[i]]-sum[r[j]]))

③ dp[r[j]]+=val[i]

朴素的dp为O(n^2)

可用线段树优化至nlogn

在 r[j]==r[i] 时,有很多细节

线段树的没调出来

30分 n^2代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm> #define N 200001 using namespace std; typedef long long LL; LL sum[N],dp[N];
int vis[N]; struct node
{
int l,r,p;
}e[N]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} bool cmp(node p,node q)
{
if(p.l!=q.l) return p.l<q.l;
return p.r<q.r;
} int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
int n,m,x;
read(n); read(m);
for(int i=;i<=n;++i) read(x),sum[i]=sum[i-]+x;
for(int i=;i<=m;++i) read(e[i].l),read(e[i].r),read(e[i].p);
sort(e+,e+m+,cmp);
memset(dp,-,sizeof(dp));
for(int i=;i<=m;i++)
{
LL tmp=-1e18; bool ok=false;
dp[e[i].r]=max(dp[e[i].r],e[i].p-(sum[e[i].r]-sum[e[i].l-]));
tmp=dp[e[i].r];
for(int j=i-;j;j--)
if(e[j].r<e[i].l) dp[e[i].r]=max(dp[e[i].r],dp[e[j].r]+e[i].p-(sum[e[i].r]-sum[e[i].l-]));
else if(e[j].r<e[i].r) dp[e[i].r]=max(dp[e[i].r],dp[e[j].r]+e[i].p-(sum[e[i].r]-sum[e[j].r]));
else if(vis[e[j].r]!=i) // 一个e[i].p只能累计一次到一个e[j].r 里
{
if(e[j].r==e[i].r) ok=true;//e[i].r==e[j].r 时,r 可能被 前两种情况修改过,但累计的话只能是用没有修改过的
else dp[e[j].r]+=e[i].p,vis[e[j].r]=i;
}
if(ok) dp[e[i].r]=max(dp[e[i].r],tmp+e[i].p);
}
LL ans=;
for(int i=;i<=n;i++) ans=max(ans,dp[i]);
printf("%I64d",ans);
}

std

#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 = , d;
bool nag = ;
do {
d = getchar();
if (d == '-')
nag = ;
} while (!isdigit(d));
do
s = s * + d - , 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 = ;
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 = ;
p-> l = l;
p-> r = r;
if (l + < 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 + == 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 * ];
n = nextInt();
m = nextInt();
rtf = sgtBuild(, n + );
rtc = sgtBuild(, n + );
s[] = ;
for (int i = ; i <= n; i ++)
s[i] = s[i - ] + nextInt();
for (int i = ; i < m; i ++) {
q[i]. l = nextInt();
q[i]. r = nextInt();
q[i]. v = nextInt();
}
sort(q, q + m, cmpObj);
ans = ;
for (int i = ; i < m; i ++) {
qw res0 = max(sgtQry(rtf, , q[i]. l), 0LL) - s[q[i]. r] + s[q[i]. l - ];
qw res1 = sgtQry(rtc, q[i]. l, q[i]. r + ) - s[q[i]. r];
qw res = max(max(res0, res1), sgtQry(rtf, q[i]. r, n + )) + 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("%I64d %I64d\n",res,ans);
}
printf(lld "\n", ans);
}

没跳出来&&不想调的线段树

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm> #define N 200001 using namespace std; typedef long long LL; LL sum[N]; LL mx1[N<<],mx2[N<<],f[N<<]; LL t1,t2; struct node
{
int l,r,p;
}e[N]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} bool cmp(node p,node q)
{
if(p.l!=q.l) return p.l<q.l;
return p.r<q.r;
} void change(int k,int l,int r,int pos,LL w,int ty)
{
if(l==r)
{
if(ty==) mx1[k]=max(mx1[k],w);
else mx2[k]=max(mx2[k],w);
return;
}
int mid=l+r>>;
if(pos<=mid) change(k<<,l,mid,pos,w,ty);
else change(k<<|,mid+,r,pos,w,ty);
mx1[k]=max(mx1[k<<],mx1[k<<|])+f[k];
mx2[k]=max(mx2[k<<],mx2[k<<|])+f[k];
} int query(int k,int l,int r,int opl,int opr,int ty)
{
if(l>=opl && r<=opr)
{
if(ty==) return max(t1,mx1[k]);
return max(t2,mx2[k])a;
}
int mid=l+r>>;
if(opr<=mid) return query(k<<,l,mid,opl,opr,ty)+f[k];
if(opr>mid) return query(k<<|,mid+,r,opl,opr,ty)+f[k];
return max(query(k<<,l,mid,opl,opr,ty),query(k<<|,mid+,r,opl,opr,ty))+f[k];
} void add(int k,int l,int r,int pos,int w)
{
if(l==pos)
{
f[k]+=w;
mx1[k]+=w;
mx2[k]+=w;
return;
}
int mid=l+r>>;
if(pos<=mid) add(k<<,l,mid,pos,w),add(k<<|,mid+,r,mid+,w);
else add(k<<|,mid+,r,pos,w);
mx1[k]=max(mx1[k<<],mx1[k<<|])+f[k];
mx2[k]=max(mx2[k<<],mx2[k<<|])+f[k];
} int main()
{
// freopen("8.in","r",stdin);
// freopen("c.out","w",stdout);
int n,m,x; LL ans=;
read(n); read(m);
for(int i=;i<=n;++i) read(x),sum[i]=sum[i-]+x;
for(int i=;i<=m;++i)
read(e[i].l),read(e[i].r),read(e[i].p);
sort(e+,e+m+,cmp);
memset(mx2,-,sizeof(mx2));
memset(mx1,-,sizeof(mx1));
LL now;
for(int i=;i<=m;i++)
{
t1=query(,,n,e[i].l,e[i].r,);//2
t2=query(,,n,e[i].r,n,);
now=t1+e[i].p-sum[e[i].r];//
now=max(now,t2+e[i].p);
t2=query(,,n,,e[i].l,);
now=max(now,t2+e[i].p-sum[e[i].r]+sum[e[i].l-]);//
ans=max(ans,now);
add(,,n,e[i].r,e[i].p);
change(,,n,e[i].r,now+sum[e[i].r],);
change(,,n,e[i].r,now,); printf("%I64d %I64d\n",now,ans);
}
printf("%I64d",ans);
}

2017北京国庆刷题Day4 morning的更多相关文章

  1. 2017北京国庆刷题Day4 afternoon

    期望得分:100+100+0=200 实际得分:5+0+0=5 每加入一个数,x的因数位置++ 注意:根号x枚举时,如果x是完全平方数,根号x会重复累计2次,要减去 考场上没减,5分 /(ㄒoㄒ)/~ ...

  2. 2017北京国庆刷题Day1 afternoon

    期望得分:100+100+100=300 实际得分:100+100+100=300 T1 一道图论好题(graph) Time Limit:1000ms   Memory Limit:128MB 题目 ...

  3. 2017北京国庆刷题Day7 morning

    期望得分:100+0+100=200 实际得分:100+20+0=120 离散化搞搞 #include<cstdio> #include<iostream> #include& ...

  4. 2017北京国庆刷题Day5 afternoon

    期望得分:100+60+100=260 实际得分:0+60+40=100 设图中有m个环,每个环有si条边,有k条边不在环中 ans= (2^s1 -2)*( 2^s2 -2)* (2^s3 -2)… ...

  5. 2017北京国庆刷题Day3 morning

    期望得分:100+60+0=160 实际得分:100+30+0=130 考场上用的哈希 #include<cstdio> #include<cstring> #include& ...

  6. 2017北京国庆刷题Day2 afternoon

    期望得分:100+100+50=250 实际得分:100+70+50=220 T1 最大值(max) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一 ...

  7. 2017北京国庆刷题Day2 morning

    期望得分:100+100+40=240 实际得分:100+40+0=140 T1 一道图论神题(god) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK ...

  8. 2017北京国庆刷题Day5 morning

    期望得分:0+60+60=120 实际得分:0+30+60=90 令g=gcd(X11,X12,X13……) 则行列式可能为D的充要条件为g|D 1.g|D为必要条件: 由定义来算行列式的时候,每一项 ...

  9. 2017北京国庆刷题Day6 afternoon

    期望得分:100+100+40=240 实际得分:100+0+40=140 二进制拆分.二进制前缀和 #include<cstdio> #include<iostream> u ...

随机推荐

  1. 【BZOJ2154】Crash的数字表格(莫比乌斯反演)

    [BZOJ2154]Crash的数字表格(莫比乌斯反演) 题面 BZOJ 简化题意: 给定\(n,m\) 求\[\sum_{i=1}^n\sum_{j=1}^mlcm(i,j)\] 题解 以下的一切都 ...

  2. 【BZOJ3675】序列分割(斜率优化,动态规划)

    [BZOJ3675]序列分割(斜率优化,动态规划) 题面 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得 ...

  3. [Luogu2073]送花

    题面 题目背景 小明准备给小红送一束花,以表达他对小红的爱意.他在花店看中了一些花,准备用它们包成花束. 题目描述 这些花都很漂亮,每朵花有一个美丽值W,价格为C. 小明一开始有一个空的花束,他不断地 ...

  4. ls-grep-find组合命令解决企业问题实战

    ls -l|grep “^d”  以d开头 ls -lF  给不同文件类型加不同标志 ls -lF|grep  “/$” 以/结尾 ls -lF|grep  / find ./ -type d fin ...

  5. WPF自学入门(六)WPF带标题的内容控件简单介绍

    在WPF自学入门(二)WPF-XAML布局控件的文章中分别介绍StackPanel,WarpPanel,DockPanel,Grid,Canvas五种布局容器的使用,可以让我们大致了解容器可以使用在什 ...

  6. 异步解决方案promise及源码实现

    js语言的特性,造就了特别的异步处理方式,我记得以前用的最多的就是回调函数,那个时候写jquery的ajax时候,特别喜欢写这种代码: $.ajax({ method:'get', url:" ...

  7. 我的C++学习之旅

    说在前面:1.学习缘由及学习途径: 在学了Python,c#(自认为未精通)之后,我决定学一下C++. 于是去网上找视频教程,发现都不适合我这种有一定基础的自学者,要么是不完整的高级教程,要么是零基础 ...

  8. Ubuntu14.04安装pycharm用于Python开发环境部署,并且支持pycharm使用中文输入

    一.目标 实现在Linux下用pycharm调试工具/Python开发 Linux使用vi/vim工具写Python,缺点:调试不方便,无代码提示.跳转等诸多功能. Windows使用idle/pyc ...

  9. BZOJ4825 单旋

    分析:一道水题,去年考场发现了特点但是不会splay维护挂了,然后现在我写了个treap. 画一画图就可以解决这道题了,自己试一下. 代码如下: #include<bits/stdc++.h&g ...

  10. win8.1下无法运行vc++6.0的解决方法

    参考网址: http://wenku.baidu.com/link?url=A6mzeCDLNW1vCV7Vm5p83jqSzguiOFlH5FX-7kdN9NJXS_ORXYuaVDn1Prnz_F ...