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;
}