2105. 【NOIP2016普及组复赛】魔法阵
2017-08-15 21:25
253 查看
题目描述
题目分析
这一道题就是一个前缀和与后缀和的问题。如果我们已经确定了A物品和B物品,我们该怎样知道组成ABCD四个物品的方案数呢?
我们只要求另外两个CD点对的方案数就行了。
我们假设sum[i]为从第i个点到第n个点的CD点对方案数,那公式就是:
sum[j]=sum[j+1]+w[j]∗w[j+i]
其中j是枚举1~n的点,而i是枚举CD距离,w[i]是指魔法值为i的物品数。
我们又假设ans[i][1−4]为魔法值为i的点分别作为A~D点的方案数。
那么有以下公式:
ans[j][0]=ans[j][0]+w[j+2∗i]∗a[j+8∗i+1];
ans[j+2∗i][1]=ans[j+2∗i][1]+w[j]∗a[j+8∗i+1];
其中k是枚举点A的位置。
接着我们又反过来做,找出CD点方案数即可。
代码
#include<cstdio> #include<cstring> using namespace std; int w[16000]; int ans[16000][4]; int a[16000],b[16000],c[41000]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x; scanf("%d",&x); w[x]++; c[i]=x; } for(int i=1;i<=(n-1)/9;i++) { a[n-i+1]=0; for(int j=n-i;j>=1;j--) { a[j]=a[j+1]+w[j]*w[j+i]; } for(int j=1;j<=n-1-8*i;j++) { ans[j][0]+=w[j+2*i]*a[j+8*i+1]; ans[j+2*i][1]+=w[j]*a[j+8*i+1]; } b[0]=0; for(int j=1;j<=n-2*i;j++) { b[j]=b[j-1]+w[j]*w[j+2*i]; } for(int j=8*i+2;j<=n;j++) { ans[j][2]+=w[j+i]*b[j-8*i-1]; ans[j+i][3]+=w[j]*b[j-8*i-1]; } } for(int i=1;i<=m;i++) { printf("%d %d %d %d\n",ans[c[i]][0],ans[c[i]][1],ans[c[i]][2],ans[c[i]][3]); } return 0; }
相关文章推荐
- 初中OJ2105【NOIP2016普及组复赛】魔法阵
- 【NOIP2016普及组复赛】魔法阵
- 【NOIP2016普及组】复赛——魔法阵
- noip2016普及组复赛第四题 T4魔法阵
- 【NOIP2016普及组复赛】魔法阵
- NOIP2016普及组复赛第一题的ACC程序加题解pascal
- noip2016普及组T4 魔法阵(magic)(错误)
- 【NOIP2016普及组】复赛——回文日期
- NOIP2016普及组复赛第1题:买铅笔
- NOIP 2016 普及组 复赛 pencil 买铅笔
- 【原创】【NOIP2016普及组】魔法阵
- NOIP2016普及组第四题——魔法阵
- ◆竞赛题目◆◇NOIP2016普及组◇ 魔法阵
- 【统计】NOIP2016普及组[魔法阵]题解
- 【NOIP2016普及组】复赛——买铅笔
- NOIP2016普及组第四题——魔法阵
- NOIP2016-普及组复赛-第2题-回文日期
- NOIP2016普及组复赛第一题——买铅笔
- magic(NOIP2016普及组复赛)
- NOIP2016普及组复赛解题报告