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