2105. 【NOIP2016普及組複賽】魔法陣
阿新 • • 發佈:2019-02-20
題目描述
題目分析
這一道題就是一個字首和與字尾和的問題。
如果我們已經確定了A物品和B物品,我們該怎樣知道組成ABCD四個物品的方案數呢?
我們只要求另外兩個CD點對的方案數就行了。
我們假設sum[i]為從第i個點到第n個點的CD點對方案數,那公式就是:
其中j是列舉1~n的點,而i是列舉CD距離,
我們又假設
那麼有以下公式:
其中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;
}