【除草】一些稍难题

来源:互联网 发布:pdf acrobat pro mac 编辑:程序博客网 时间:2024/04/28 14:09

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 0
原创粉丝点击