BC-40 HDU5225 HDU 5226 【水】

来源:互联网 发布:java计算器加减乘除 编辑:程序博客网 时间:2024/05/29 11:45

第一题,给你一个矩形的面积,求矩形的最小周长。

可知,当两边长最接近的时候,周长最小。所以可以从sqrt(s)开始枚举,如果能够整除,就输出计算的周长

#include <stdio.h>#include <math.h>#define ll __int64int main(){    int T;    scanf("%d",&T);    while(T--)    {        ll n;        scanf("%I64d",&n);        ll tmp=sqrt(n),i;        for(i=tmp;i<=n;i++)            if(n%i==0) break;        printf("%I64d\n",(i+n/i)*2);    }    return 0;}

第二题,给你一串n长的序列。序列中数字是1-n。求所有字典序比给定序列小的序列的逆序数之和。

字典序大小定义:比较第一个不相同的数字,数字小的字典序小。如果序列比完了,那么长度小的字典序小。

这道题。。想了半个小时。。的样子?啊!我知道怎么做了!然后各种debug各种WA。。。。到了第二天。。。。终于。。。我在想我的心思为什么如此不缜密。。。

这样的,对于一串序列,例:

10

5 3 6 7 2 9 8 1 4 10


额,在举例之前要说,对于n个数的全排列的逆序数之和显然是固定的,这里可以推出公式来,设cal[i]为i个数的全排列的逆序数的和。

在枚举的时候可以把序列分成三部分。
通过统计可以得到比对到第i个数的时候,(i,n]中比a[i]小的个数(j),那么就有j*A[n-i]中排列使得字典序比原序列小。
对于每一个比a[i]小的数的序列中,我们已经知道在A[n-i]种排序中逆序数的和为cal[n-i]了,还要加上在i之前的序列的逆序数之和和[1,i)对[i,n]产生的逆序数,还有在替换第i个数的时候,替换后的a[i]产生的逆序数

好难解释啊。。。。。不过应该不是很难推出来!!!!体会一下思路。
然后线段树真的不能开两倍啊喂!!!然后杭电真的不支持long long 啊喂!
标准的线段树应该开4N+100。

#include <stdio.h>#include <iostream>using namespace std;#define mod 1000000007#define llt long longllt cal[110],a[110],A[110];llt tree[330];template<class T>inline char read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' | c > '9') && c != '-' && c != EOF) c = getchar();    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return c;}template <class T>inline void write(T n) {    if(n < 0) {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n) {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);}void create(llt l,llt r,llt rt){    tree[rt]=0;    if(l==r) return;    llt mid=(l+r)>>1;    create(l,mid,rt<<1);    create(mid+1,r,rt<<1|1);}llt query(llt ll,llt rr,llt l,llt r,llt rt){    if(l==ll&&r==rr) return tree[rt];    llt mid=(l+r)>>1;    if(rr<=mid) return query(ll,rr,l,mid,rt<<1);    else if(ll>mid) return query(ll,rr,mid+1,r,rt<<1|1);    else    {        llt ans=query(ll,mid,l,mid,rt<<1);        ans+=query(mid+1,rr,mid+1,r,rt<<1|1);        return ans;    }}void update(llt l,llt r,llt rt,llt x){    if(l==x&&r==x)    {        tree[rt]++;        return;    }    llt mid=(l+r)>>1;    if(x<=mid) update(l,mid,rt<<1,x);    else update(mid+1,r,rt<<1|1,x);    tree[rt]=tree[rt<<1]+tree[rt<<1|1];}void init(){    cal[0]=0,cal[1]=0,cal[2]=1;    A[1]=1;A[0]=1;    for(int i=2;i<=100;i++)    {A[i]=(A[i-1]*i)%mod;    }    for(int i=3;i<=100;i++)    {        cal[i]=((i*cal[i-1])%mod+(i*(i-1)*A[i-1]/2)%mod)%mod;    }}llt sum(llt x){    return ((x-1)*x)/2;}int main(){    init();llt n;    while(scanf("%I64d",&n)!=EOF)    {        llt ans=0;        llt i,j,pre=0,tmp=0;        llt k;        create(1,100,1);        for(i=1;i<=n;i++)        {            read(a[i]);            tmp=query(a[i]+1>100?100:a[i]+1,100,1,100,1);            j=n-i-(n-a[i]-tmp);  //比a[i]小的个数            if(j<=0) continue;            k=A[n-i];llt p=cal[n-i];            ans=(ans+((p*j)%mod+(pre*k*j)%mod+(sum(j)*k)%mod)%mod)%mod;            update(1,100,1,a[i]);            pre+=j;        }        printf("%I64d\n",ans);    }    return 0;}



0 0