【URAL刷题记】 URAL 1090~URAL 1097

URAL 1090

/*
K行士兵站成N列,每个士兵都有自己的高度,一个士兵在该行中每有一个站在他左边而比他矮的士兵就跳一下,求哪一行跳的次数最多
解答:就是求最大逆序数,我是用BIT写的
*/
#include<cstdio>
#include<cstring>
const int maxn=10010;

int TN;
int T[maxn];
void add(int x,int v){ for(;x<=TN;x+=x&-x) T[x]+=v; }
int sum(int x){ int v=0; for(;x;x-=x&-x) v+=T[x]; return v; }

int a[maxn];
int n,m;

int main(){
//  freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);

    int mx=0,mxi=1;
    for(int p=1;p<=m;++p){
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);

        memset(T,0,sizeof T);
        TN=n;
        int res=0;
        for(int i=n;i>=1;--i){
            res+=sum(a[i]);
            add(a[i],1);
        }
        if(res>mx) mx=res,mxi=p;
    }
    printf("%d\n",mxi);
//  for(;;);
    return 0;
}

URAL 1091

/*
求$N$以内的大小为$K$的数集个数,满足数集内的数的$gcd>1$

设f[x]表示公约数是x的倍数的情况数,g[x]表示公约数恰好是x的情况数
有:
$f_n=\sum_{n|d}g(d)$
$g_n=\sum_{n|d}f(d)*\mu(\frac{d}{n})$
其中$f_n=\binom{\lfloor\frac{N}{d}\rfloor}{k}$
故$$g_n=\sum_{2\leq n \leq N} \sum_{n|d} \binom{\lfloor\frac{N}{d}\rfloor}{k} \mu(\frac{d}{n})$$
交换后
$$g_n=\sum_d \binom{\lfloor\frac{N}{d}\rfloor}{k} \sum_{n|d}\mu(\frac{d}{n})[n \geq 2]$$
故
$$g_n=\sum_{1\leq d \leq N} \binom{\lfloor\frac{N}{d}\rfloor}{k} ([n==1] - \mu(d))$$
即
$$g_n=\sum_{2\leq d \leq N} \binom{\lfloor\frac{N}{d}\rfloor}{k}$$
*/
#include<cstdio>
#include<cstring>

typedef long long LL;

const int maxn=1010;
const int maxp=1010;

int prime[maxp],primeN;
int phi[maxn], mu[maxn];
LL sphi[maxn];int smu[maxn];
bool isprime[maxn];
void gen(int n) {
    primeN = 0;
    memset(isprime, 1, sizeof isprime);

    isprime[0]=isprime[1]=0;
    phi[1]=1, mu[1]=1;
    for(int i=2,p;i<n;++i){
        if (isprime[i]) {
            prime[primeN ++]=p=i;
            phi[p]=p-1, mu[p]=-1;
        }

        for(int j=0,x;j<primeN && (x=i*(p=prime[j]))<n;++j){
            isprime[x] = 0;

            if(!(i%p)){
                phi[x]=phi[i]*p, mu[x]=0;
                break;
            } else {
                phi[x]=phi[i]*(p-1), mu[x]=-mu[i];
            }
        }
    }
}

const int MAXN=60;
int K,N;
LL C[MAXN][MAXN];

int main(){
//  freopen("in.txt","r",stdin);
    scanf("%d%d",&K,&N);

    gen(N+1);
    for(int i=0;i<=N;++i){
        C[i][0]=C[i][i]=1;
        for(int j=1;j<i;++j)
            C[i][j]=C[i-1][j]+C[i-1][j-1];
    }

    LL res=0;

    for(int d=1;d<=N;++d)
        res+=C[N/d][K]*((d==1) - mu[d]);

/*  for(int n=2;n<=N;++n)
        for(int d=n;d<=N;++d)if(d%n==0)
            res+=C[N/d][K]*mu[d/n];
*/  
    printf("%d\n",res<=10000 ? res : 10000);
//  for(;;);
    return 0;
}

URAL 1092

URAL 1093

/*
三维空间里的投飞镖 给出靶子的中心cx cy cz 法向量nx,ny,nz 靶子半径 R飞镖的初始位置和速度,
问你飞镖能不能打靶

DOT((nx,ny,nz) , (mx,my,mz)-(cx,xy,cz)) = 0即可
坑啊,这题飞镖可能直接在靶子里。。。方程A=B=C=0的情况下,由题意——“打靶”,故应该输出MISS 
*/
#include<cstdio>
#include<cmath>

const double eps=1e-12;
int dcmp(double x){ return fabs(x)<eps ? 0 : (x>0 ? 1 : -1); }

const double g=10;

double Length2(double x,double y,double z){ return x*x+y*y+z*z; }
double Cx,Cy,Cz,Nx,Ny,Nz,R,Sx,Sy,Sz,Vx,Vy,Vz;
void solve(){
    scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&Cx,&Cy,&Cz,&Nx,&Ny,&Nz,&R,&Sx,&Sy,&Sz,&Vx,&Vy,&Vz);
    double A=-0.5*g*Nz, B=Vx*Nx+Vy*Ny+Vz*Nz, C=(Sx-Cx)*Nx+(Sy-Cy)*Ny+(Sz-Cz)*Nz; //Ax^2+bx+c=0
    if(A==0){
        if(B==0){

        }else{
            double t;
            t=(-C)/B;
            if(t>=0 && Length2(Sx+Vx*t-Cx,Sy+Vy*t-Cy,Sz+Vz*t-0.5*g*t*t-Cz)<R*R){
                puts("HIT"); return;
            }
        }
    }else{
        double D=B*B-4*A*C;
        if(D>=0){
            double t;
            t=(-B+sqrt(D))/(2*A);
            if(t>=0 && Length2(Sx+Vx*t-Cx,Sy+Vy*t-Cy,Sz+Vz*t-0.5*g*t*t-Cz)<R*R){
                puts("HIT"); return;
            }
            t=(-B-sqrt(D))/(2*A);
            if(t>=0 && Length2(Sx+Vx*t-Cx,Sy+Vy*t-Cy,Sz+Vz*t-0.5*g*t*t-Cz)<R*R){
                puts("HIT"); return;
            }
        }
    }
    puts("MISSED");
}

int main(){
//  freopen("in.txt","r",stdin);
    solve();
//  for(;;);
    return 0;
}

URAL 1094

/*
给一个操作序列,问最后显示什么。。操作序列:< or > or 字符
<表示光标往左,>表示光标向右,字符表示写一个字符(覆盖)
然后显示屏最多80个字符,跑到最右边或最左边默认回到最左位置
*/
#include<cstdio>
#include<cstring>

const int maxn=100010;

int n;
char s[maxn];
char ans[110]; int p;

int main(){
//  freopen("in.txt","r",stdin);

    for(int i=1;i<=80;++i)ans[i]=' '; ans[81]=0;

    p=1;
    gets(s); n=strlen(s);
    for(int i=0;i<n;++i){
        switch (s[i]){
            case '>': ++p; break;
            case '<': --p; break;
            default: ans[p]=s[i]; ++p; break;
        }
        if(p<=0||p>80) p=1;
    }
    puts(ans+1);
//  for(;;);
    return 0;
}

URAL 1095

/*
一个不超过20位的整数,一定有1234,把他们重排,使得结果是7的倍数
1234的排列mod7余0123456各存一个
剩下的非零数按顺序拎出来,在后面接上mod7互补的1234排列,最后填0
*/
#include<cstdio>
#include <cstring>

const int base[7]={4123, 2134, 1342, 1243, 2341, 1234, 1324};

int num[20];
char s[110];
int n;
void solve(){
    scanf("%s",s); n=strlen(s);
    memset(num,0,sizeof num);
    for(int i=0;i<n;++i)++num[s[i]-'0'];
    for(int i=1;i<=4;++i)--num[i];
    int x=0;
    for(int i=1;i<=9;++i)
        for(int j=0;j<num[i];++j){
            putchar('0'+i);
            x=(x*10+i)%7;
        }
    x=x*10000%7;
    printf("%d",base[x]);
    {
        int i=0;
        for(int j=0;j<num[i];++j){
            putchar('0'+i);
            x=(x*10+i)%7;
        }
    }
    putchar('\n');
}

int main(){
    int kase;scanf("%d",&kase);
    while(kase--)solve();
    return 0;
}

URAL 1096

/*
有一堆人,每个人手里有个盘子,两面各有一个编号,两面没啥区别但是正面是他要的数。
一个人有一个随机的盘子,和一个要得数
然后他去和其他人交换。当且仅当他手里的盘子上有对方需要的数,他们才能交换。问换到想要的数的最小步骤

直接BFS。
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

typedef pair<int,int> P;

const int maxn=2010;

int mp[maxn][maxn];

P Q[100000]; int l,r;
int d[maxn][maxn];
P p[maxn][maxn];


void dfs(int x1,int x2){
    if(p[x1][x2].first)dfs(p[x1][x2].first,p[x1][x2].second); else return;
    printf("%d\n",mp[x1][x2]);
}

int m;
void solve(){
    scanf("%d",&m);
    for(int i=1;i<=m;++i){
        int x,y;scanf("%d%d",&x,&y);
        mp[x][y]=i;
    }

    int t,sx,sy;
    scanf("%d%d%d",&t,&sx,&sy);

    memset(d,255,sizeof d);
    l=r=0;
    Q[r++]=P(sx,sy); d[sx][sy]=0;
    for(;l!=r;++l){
        int ux1=Q[l].first,ux2=Q[l].second;
        if(ux1==t || ux2==t)break;
        for(int vx=1;vx<=2000;++vx){
            if(mp[ux1][vx]){
                if(!~d[ux1][vx]){
                    d[ux1][vx]=d[ux1][ux2]+1;
                    p[ux1][vx]=P(ux1,ux2);
                    Q[r++]=P(ux1,vx);
                }
            }
            if(mp[ux2][vx]){
                if(!~d[ux2][vx]){
                    d[ux2][vx]=d[ux1][ux2]+1;
                    p[ux2][vx]=P(ux1,ux2);
                    Q[r++]=P(ux2,vx);
                }
            }
        }
    }
    if(d[Q[l].first][Q[l].second]==-1){
        puts("IMPOSSIBLE");
    }else{
        printf("%d\n",d[Q[l].first][Q[l].second]);
        dfs(Q[l].first,Q[l].second);
    }
}
int main(){
//  freopen("in.txt","r",stdin);
    solve();
//  for(;;);
    return 0;
}

URAL 1097

/*
题意:给一个每一位上都有一个数字的正方形, 要选取一个大小为A*A的正方形, 问覆盖到的最大值最小为多少.

二分答案,因为正方形左下角应尽量往左往下靠,所以离散化一下后,只有n^2个可能位置。
然后判断一下是否可行即可。
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn=110;
struct block{
    int z,s,x,y;
}a[maxn];
int X[maxn],Y[maxn];
int XN,YN;
int A,L;
int m;

bool check(int lam){
    for(int i=0;i<XN;++i)if(X[i]+L<=1+A) for(int j=0;j<YN;++j)if(Y[j]+L<=1+A){
        int x=X[i],y=Y[j];
        int k;
        for(k=0;k<m&&(a[k].z<=lam || a[k].x+a[k].s<=x || x+L<=a[k].x || a[k].y+a[k].s<=y || y+L<=a[k].y);++k);
        if(k==m){
//          printf("%d %d\n",x,y);
            return 1;
        }
    }
    return 0;
}

void solve(){
    scanf("%d%d%d",&A,&L,&m);
    XN=0,YN=0;
    for(int i=0;i<m;++i){
        int z,s,x,y; scanf("%d%d%d%d",&z,&s,&x,&y);
        a[i]=(block){z,s,x,y};
        X[XN++]=x+s,Y[YN++]=y+s;
    }
    X[XN++]=1,Y[YN++]=1;
    sort(X,X+XN);XN=unique(X,X+XN)-X;
    sort(Y,Y+YN);YN=unique(Y,Y+YN)-Y;

    int l=0,r=101;
    check(l);
    if(!check(r)){ puts("IMPOSSIBLE"); return; }
    while(l+1<r){
        int m=(l+r)>>1;
        if(check(m))r=m;else l=m;
    }
    printf("%d\n",r);
}
int main(){
//  freopen("in.txt","r",stdin);
    solve();
//  for(;;);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yeziqing10/article/details/50660091