P2119 魔法阵(优化枚举,数学运算优化)难度⭐⭐⭐★

P2119 魔法阵

%%%

#include
#include
#include
#include
#include
#include

#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r)/2
#define over(i,s,t) for(register int i=s;i<=t;++i)
#define lver(i,t,s) for(register int i=t;i>=s;--i)

using namespace std;
typedef long long ll;//全用ll可能会MLE,ll比int占的内存大
const ll N=1000007;
const ll INF=1e9+9;
const ll mod=2147483647;
const double EPS=1e-10;//-10次方约等于趋近为0
const double Pi=3.1415926535897;

ll n,m,a[N],b[N],c[N],d[N];
ll x[N],vis[N];

//k>=1
//n=9*t+k
//1<=A<=n-9*t-1
//t+1<=B<=n-7*t-1
//9*t+2<=D<=n-1(k==1&&A==1)

int main()
{
    scanf("%lld%lld",&n,&m);
    over(i,1,m)
    scanf("%lld",&x[i]),vis[x[i]]++;
    for(int t=1;9*t<n;++t)
    {
        ll sum=0;
        for(int D=9*t+2;D<=n;++D)//A至少为1,k至少为1
        {
            //对于ABCD来说都是从小到大的
            ll A=D-9*t-1;//减去至少为1的K
            ll B=A+2*t;
            ll C=D-t;
            
            sum+=vis[A]*vis[B];
            //求的是第i件物品成为ABCD的次数,所以重复的x[i]没有任何影响
            c[C]+=sum*vis[D];
            d[D]+=sum*vis[C];
        }
        
        sum=0;
        
        for(int A=n-9*t-1;A;--A)//倒序求后缀和
        {
            ll B=A+2*t;
            ll C=A+8*t+1;//有一个k>=1
            ll D=A+9*t+1;
            
            sum+=vis[C]*vis[D];
            a[A]+=vis[B]*sum;
            b[B]+=vis[A]*sum;
        }
    }
    
    over(i,1,m)
    printf("%lld %lld %lld %lld\n",a[x[i]],b[x[i]],c[x[i]],d[x[i]]);
    
    return 0;
}


你可能感兴趣的:(#,优化枚举)