【除草】一些稍难题

48 篇文章 0 订阅
35 篇文章 0 订阅

hdu4623

通过打表发现很多数字在考虑互质的情况是等价的,因此将其压成同一种数字,最后再乘以排列数就可以状压dp了

一开始判等价的时候,没有考虑可以不用比较自身,导致算出来的状态有500W+,实际上只有200W不到

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
using namespace std;
int n,m,g[30][30],D[30],d[30],lim,u[30],cnt,p[30],q[30],C[30];
short f[5600000][29];
int t,mo;
int gcd(int a,int b)
{
	for (;a%b;) {
		int t=a%b;
		a=b;
		b=t;
	}
	return b;
}
bool cmp(int i,int j,int n)
{
	for (int k=1;k<=n;k++)
		if (i!=k && j!=k) {
			if ((gcd(i,k)==1 && gcd(j,k)!=1)) return 1;
			else if ((gcd(i,k)!=1 && gcd(j,k)==1)) return 1;
		}
	return 0;
}
void origin(int n)
{
	C[1]=1;
	for (int i=2;i<=n;i++) C[i]=(C[i-1]*i)%mo;
	for (int i=1;i<=n;i++) d[i]=0,u[i]=0;
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=n;j++)
			if (gcd(i,j)==1) {
				g[i][j]=1; 
			}
	}
	cnt=0;
	lim=1;
	for (int i=1;i<=n;i++)
		if (!u[i]) {
			q[++cnt]=i,p[i]=cnt;
			d[cnt]=1;
			for (int j=i+1;j<=n;j++)
				if (!cmp(i,j,n)) u[j]=1,d[cnt]++;
			lim*=(d[cnt]+1);
		}
	D[0]=1;
	for (int i=1;i<=cnt;i++)
		D[i]=D[i-1]*(d[i]+1);
}
inline bool check(int s,int i)
{
	return (s/D[i-1])%(d[i]+1);
}
inline int change(int s,int i)
{
	return s-=(1*D[i-1]);
}
int main()
{
	freopen("input.txt","r",stdin);
	scanf("%d",&t);
	for (;t;t--) {
		scanf("%d%d",&n,&mo);
		origin(n);
		//cout<<lim<<endl;
		for (int s=1;s<lim;s++)
			for (int j=1;j<=cnt;j++)
				if (check(s,j)) {
					int ns=change(s,j);
					if (!ns) {
						f[s][j]=1;
						continue;
					}
					f[s][j]=0;
					for (int k=1;k<=cnt;k++)
						if (g[q[j]][q[k]] && check(ns,k)) {
							f[s][j]=((int)f[s][j]+f[ns][k])%mo;
						}
				}
		int ans=0;
		for (int i=1;i<=cnt;i++)
			ans=(ans+f[lim-1][i])%mo;
		for (int i=1;i<=cnt;i++)
			ans=(ans*C[d[i]])%mo;
		printf("%d\n",ans);
		//cout<<lim<<endl;
	}
	//cout<<clock()<<endl;
	return 0;
}

hdu3761

删连续一段点一定更优

发现了半平面交模板的一个漏洞(不过反正是自己写的模板,有问题也正常╮(╯▽╰)╭),似乎以前判无解的情况很少,这次就出问题了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define sqr(x) ((x)*(x))
const long double eps=1e-6;
const long double pi=acos(-1.0);
const long double oo=1e15;
using namespace std;
struct point{
    long double x,y,z,_,d;
    void print()
    {
//        printf("x=%lf y=%lf z=%lf\n",x,y,z);
        	//cout<<"x= "<<x<<" y= "<<y<<" z= "<<z<<endl;
        	cout<<x<<"x+"<<y<<"y>"<<-z<<endl;
    }
}a[500000],p[500000],St[500000];
int u[500000],st[500000],U[500000];
int n;
inline long double cr(point &e,point &r) {return e.x*r.y-e.y*r.x;}
inline long double dot(point &e,point &r) {return e.x*r.x+e.y*r.y+e.z*r.z;}
inline void cross(point p,point q,point &e)
{
    e.x=p.y*q.z-p.z*q.y;
    e.y=p.z*q.x-p.x*q.z;
    e.z=p.x*q.y-p.y*q.x;
}
inline void ori(point &a)
{
    a._=atan2(a.y,a.x);
    a.d=a.z/sqrt(sqr(a.x)+sqr(a.y));
}
inline bool cmp(int i,int j)
{
    long double tmp=p[i]._-p[j]._;
    if (fabs(tmp)>pi/2) return tmp<-eps;
    tmp=cr(p[i],p[j]);
    if (fabs(tmp)>eps) return tmp>eps;
    return p[i].d<p[j].d;
}
inline bool check(point &p,point I)
{
    if (dot(p,I)>eps) return 1;
    return 0;
}
inline bool equ(point &p) 
{
	return fabs(p.x)<eps && fabs(p.y)<eps && fabs(p.z)<eps;
}
bool check(int ans)
{
    if (ans==n) return 1;
   int tot=0;
   ++tot,p[tot].x=0,p[tot].y=-1,p[tot].z=oo;
   ++tot,p[tot].x=1,p[tot].y=0,p[tot].z=oo; 
	 ++tot,p[tot].x=0,p[tot].y=1,p[tot].z=oo; 
   ++tot,p[tot].x=-1,p[tot].y=0,p[tot].z=oo;
   for (int i=n+n;i>=n+1;i--) {
        point A=a[i-1],B=a[i+ans];
        point l;
        cross(A,B,l);
        if (dot(l,a[i])>-eps) {
            l.x=-l.x,l.y=-l.y,l.z=-l.z;
        }     
        p[++tot]=l;
   }
   for (int i=1;i<=tot;i++) ori(p[i]),U[i]=i;
   int op=5;
   for (int i=6;i<=tot;i++)
  		if (cmp(i,op)) op=i;
	 for (int i=5;i<op;i++) U[++tot]=U[i];
	 int cnt=0;
   for (int i=1,j=op;i<=4 || j<=tot;) {
   		if ((i>4) || cmp(U[i],U[j]) || j>tot) {
   			u[++cnt]=U[i];
   			i++;
   		}
   		else {
   			u[++cnt]=U[j];
   			j++;
   		}
   }
//   for (int i=1;i<=cnt;i++) cout<<u[i]<<' ';cout<<endl;
//   sort(u+1,u+cnt+1,cmp);
//   for (int i=1;i<=cnt;i++) cout<<u[i]<<' ';cout<<endl;
   int h,r;
   st[h=r=1]=u[1]; 
   for (int i=2;i<=cnt;i++) {
       if (fabs(cr(p[u[i]],p[u[i-1]]))<eps) continue;
       for (;(h<r) && (!check(St[r],p[u[i]]));r--) ;
       for (;(h<r) && (!check(St[h+1],p[u[i]]));h++) ;
       st[++r]=u[i];
       cross(p[st[r-1]],p[st[r]],St[r]);
       if (equ(St[r])) return 1;
   }
   for (;(h<r) && (!check(St[r],p[st[h]]));r--) ;
   for (;(h<r) && (!check(St[h+1],p[st[r]]));h++) ;
   //cout<<h<<' '<<r<<endl;
   for (int i=h;i<=r;i++) 
  		if (st[i]<=4) return 1;
   return r-h+1<=2;
}
int main()
{
    int t;
    scanf("%d",&t);
    for (;t;t--) {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) {
            double x,y;
            scanf("%lf%lf",&x,&y),a[i].z=1;
            a[i].x=x,a[i].y=y;
            a[i+n]=a[i],a[i+n+n]=a[i];
        }
        int l=1,r=n-3;
        for (;l<=r;) {
            int mid=(l+r)>>1;
            if (check(mid)) r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",l);
    }
    return 0;
}


hdu3983

询问某一位为1,即取模后按剩余系询问一段区间。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
multiset < long long > Set;
int f[20][1<<20];
int q,t;
char ch[20000];
void origin()
{
    for (int i=0;i<=17;i++)
        for (int j=0;j<=((1<<(i+1))-1)+1;j++)
            f[i][j]=0;
}
void change(int e,int x,int cnt)
{
    x+=1;
    int lim=((1<<(e+1))-1)+1;
    for (;x<=lim;x+=(x & (-x)))
        f[e][x]+=cnt;
}
int ask(int e,int x)
{
    int sum=0;
    x+=1;
    for (;x;x-=(x & (-x)))
        sum+=f[e][x];
    return sum;
}
int main()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    scanf("%d",&t);
    for (int test=1;t;t--,test++) {
        printf("Case %d:\n",test);
        scanf("%d",&q);
        origin();
        long long bj=0;
        Set.clear();
        for (int i=1;i<=q;i++) {
            scanf("%s",ch+1);
            long long x;
            int xx;
            if (ch[1]=='I') {
                scanf("%d",&xx);x=xx;
                x-=bj;
                Set.insert(x);
                for (int j=0;j<=17;j++) {
                    int y=(x&((1<<(j+1))-1));
                    change(j,y,1);
                }
            }
            else if (ch[1]=='D') {
                scanf("%d",&xx);x=xx;
                x-=bj;
                int cnt=Set.count(x);
                if (!cnt) {
                    printf("Del error\n");
                    continue;
                }
                Set.erase(x);
                for (int j=0;j<=17;j++) {
                    int y=(x&((1<<(j+1))-1));
                    change(j,y,-cnt);
                }
                if (!Set.size()) bj=0;
            }
            else if (ch[1]=='A') {
                scanf("%d",&xx);x=xx;
                bj+=x;
            }
            else if (ch[1]=='S') {
                scanf("%d",&xx);x=xx;
                if (!Set.size()) continue;
                if (!Set.size() || (*Set.begin())+bj-x<0) {
                    printf("Sub error\n");
                    continue;
                }
                bj-=x;
            }
            else if (ch[1]=='Q' && ch[2]=='N') {
                scanf("%d",&xx);x=xx;
                x-=bj;
                int ans=Set.count(x);
                printf("%d\n",ans); 
            }
            else if (ch[1]=='Q' && ch[2]=='B') {
                scanf("%d",&xx);x=xx;
                long long l=((1<<x)-1),r=((1<<(x+1))-1);
                int mo=(1<<(x+1));
                l=((l-bj)%mo+mo)%mo,r=((r-bj)%mo+mo)%mo;
                if (l<=r) {
                    int ans=ask(x,r)-ask(x,l);
                    printf("%d\n",ans);
                }
                else {
                    int ans=(ask(x,mo-1)-ask(x,l))+ask(x,r);
                    printf("%d\n",ans);
                }
            }
        }
        printf("\n");
    }
    return 0;
}

poj 3851

特殊的最短路,有负圈,但是负圈在当前距离小于某个值的时候就会消失,因此每次把负圈抽出来处理一下,有点像消圈算法。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<iostream>
#include<ctime>
const int oo=1073741819;
using namespace std;
int n,m,cnt;
struct point
{
    int x,y,z,t;
    void scan()
    {
        scanf("%d%d%d",&x,&y,&z);
        t=-oo;
    }
}p[1010];
struct worm
{
    int a,b;
    int t,d;
}w[1010];
int f[1010];
const int maxn=1000000;
int q[maxn+10],t[1010];
bool vis[1010];
int pre[1010];
double sqr(double x)
{
    return x*x;
}
int dis(point a,point b)
{
    double d=sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)+sqr(a.z-b.z));
    return (int)(ceil(d));
}
int st[1010],Rd[1010],loc[1010],w_time,pra[1010],D[1010][1010];
void doit(int s,int &head,int &tail)
{
    int r=0;
    int k=-oo;
    w_time++;
    int i;
    for (i=s;Rd[i]!=w_time;i=pre[i]) {
        Rd[i]=w_time;
        st[++r]=i;
        loc[i]=r;
    }
    int op=loc[i],cf=0;
    for (int i=op;i<=r;i++) {
        if (p[st[i]].t>k) k=p[st[i]].t,cf=i;
    }
    if (k==-oo || k>=f[st[cf]]) return ;
    int dis=p[st[cf]].t;
    f[st[cf]]=min(f[st[cf]],dis);
    for (int i=cf-1;i>=op;i--) {
        dis+=pra[st[i]];
				if (dis<f[st[i]]) {
					f[st[i]]=min(f[st[i]],dis);
					if (!vis[st[i]]) {
						tail=tail%maxn+1;
            q[tail]=st[i];
            t[st[i]]++;
            vis[st[i]]=true;
					}
				}
		}
    for (int i=r;i>cf;i--) {
        dis+=pra[st[i]];
				if (dis<f[st[i]]) {
					f[st[i]]=min(f[st[i]],dis);
					if (!vis[st[i]]) {
						tail=tail%maxn+1;
            q[tail]=st[i];
            t[st[i]]++;
            vis[st[i]]=true;
					}
				}
    }
}
void work()
{
    p[1].scan();
    p[2].scan();
    scanf("%d",&n);
    cnt=2;
    for (int i=1;i<=n;i++)
    {
        p[++cnt].scan();
        w[i].a=cnt;
        p[++cnt].scan();
        w[i].b=cnt;
        scanf("%d%d",&w[i].t,&w[i].d);
        p[cnt-1].t=w[i].t; 
        //p[cnt].t=w[i].t+w[i].d;
    }
    for (int i=1;i<=cnt;i++)
        for (int j=i+1;j<=cnt;j++) {
            D[i][j]=D[j][i]=dis(p[i],p[j]);
//            cout<<i<<' '<<j<<' '<<D[i][j]<<endl;
          }
    for (int i=1;i<=cnt;i++) vis[i]=false,f[i]=oo,t[i]=0,pre[i]=0,pra[i]=0; 
    int head=1,tail=1;
    vis[1]=true;t[1]=1;
    f[1]=0;
    q[1]=1;
    while (head!=tail+1)
    {
        int x=q[head];
        vis[x]=false;
        head=head%maxn+1;
        if (t[x]>=cnt) {
	      	doit(x,head,tail);
	      }
        for (int i=1;i<=cnt;i++)
        if (f[i]>f[x]+D[x][i])
        {
            f[i]=f[x]+D[x][i];
            pre[i]=x,pra[i]=D[x][i];
            if (!vis[i])
            {
                tail=tail%maxn+1;
                q[tail]=i;
                t[i]++;
                vis[i]=true;
            }
        }
        for (int i=1;i<=n;i++)
        {
            int dd=0;
            if (x!=w[i].a) continue;
            dd=max(f[x],w[i].t);
            if (f[w[i].b]>dd+w[i].d)
            {
                f[w[i].b]=dd+w[i].d;
                pre[w[i].b]=x,pra[w[i].b]=w[i].d;
                if (!vis[w[i].b])
                {
                    vis[w[i].b]=true;
                    tail=tail%maxn+1;
                    t[w[i].b]++;
                    q[tail]=w[i].b;
                }
            } 
        }
       // vis[x]=false;
    }
    //for (int i=1;i<=cnt;i++) cout<<f[i]<<' ';cout<<endl;
   printf("%d\n",f[2]);
}
int main()
{
    freopen("J.in","r",stdin);
    freopen("output.txt","w",stdout);
    int times;
    scanf("%d",×);
    for (int i=1;i<=times;i++)
    work();
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值