不知不觉省选完已经颓了半个月了!!!还两个月就要NOI了。。很慌。。
前几天做NOI2016翻车以后。。今天开始先做2015Day1
第一题:
这么裸这么和善的并查集么。。(我才不会告诉你先做的时候看错了题结果竟然还有80。。数据不要这么水吧。。)
第二题:
这么SB的树剖吗!?Install就查询该点到根路径上0的个数,然后全部赋为1,Uninstall就查询以该点为跟的子树1的个数,然后赋为0。。
第三题:
这个题看起来好像也可做啊。。然而我最终还是只打了表。。还只有20分。
看看题解。哇,状压dp。
发现取一个数相当于取到它所有的质因数。然后大于根号500的质因数每个数最多只有一个(废话),小于根号500的质因数只有8个,8个!然后就可以状压了。
然后就是处理大于根号500的质因数的问题。我们可以将所有数按最大质因数(大于根号500的)排序。然后相邻相等的不重复处理就好辣!
f[i][j]表示第一个人状态为i,第二个人为
g[0/1][i][j]表示当前数放到第1/2个人后,第一个人状态为i,第二个人为
然后f[i][j]=g[0][i][j]+g[1][i][j]−f[i][j])为什么要减呢?
因为都不取的算了两次呀~
T1
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 100005
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,T,tot;
int father[N<<1],hash[N<<1];
class Operation{
public:
int x,y;bool z;
}e[N];
bool operator <(Operation a,Operation b){
return a.z>b.z;
}
int Find(int x)
{
int l=1,r=tot,rtn;
while(l<=r)
{
int mid=l+r>>1;
if(hash[mid]>=x) rtn=mid,r=mid-1;
else l=mid+1;
}
return rtn;
}
int Findf(int x){
return father[x]==x?x:father[x]=Findf(father[x]);
}
void Input_Init()
{
n=read();tot=0;
for(int i=1;i<=n;i++)
{
hash[++tot]=e[i].x=read();
hash[++tot]=e[i].y=read();
e[i].z=read();
}
sort(hash+1,hash+1+tot);
tot=unique(hash+1,hash+1+tot)-hash-1;
for(int i=1;i<=tot;i++) father[i]=i;
}
bool Solve()
{
sort(e+1,e+1+n);
for(int i=1;i<=n;i++)
{
e[i].x=Find(e[i].x);
e[i].y=Find(e[i].y);
int fx=Findf(e[i].x),fy=Findf(e[i].y);
if(!e[i].z)
{
if(fx==fy)
return false;
}
else
father[fx]=fy;
}
return true;
}
int main()
{
T=read();
while(T--)
{
Input_Init();
if(Solve()) printf("YES\n");
else printf("NO\n");
}
return 0;
}
T2
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 100005
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,cnt,m,ind;
int b[N],p[N],nextedge[N];
int son[N],fa[N],top[N],pos[N],Fpos[N],sz[N],deep[N];
class Seg_Tree{
public:
int l,r,sum,tag;
}e[N<<2];
void Add(int x,int y)
{
cnt++;
b[cnt]=y;
nextedge[cnt]=p[x];
p[x]=cnt;
}
void Dfs(int x)
{
sz[x]=1;
for(int i=p[x];i;i=nextedge[i])
{
int v=b[i];
deep[v]=deep[x]+1;
Dfs(v);sz[x]+=sz[v];
son[x]=sz[son[x]]<sz[v]?v:son[x];
}
}
void dfs(int x,int root)
{
pos[x]=++ind;top[x]=root;Fpos[pos[x]]=x;
if(!son[x]) return;
dfs(son[x],root);
for(int i=p[x];i;i=nextedge[i])
{
int v=b[i];
if(v==son[x]) continue;
dfs(v,v);
}
}
void Build(int p,int l,int r)
{
e[p].l=l,e[p].r=r,e[p].tag=-1;
if(l==r) return;
int mid=l+r>>1;
Build(p<<1,l,mid);Build(p<<1|1,mid+1,r);
}
int Len(Seg_Tree a){
return a.r-a.l+1;
}
void pushdown(int p)
{
e[p<<1].sum=e[p].tag*Len(e[p<<1]);
e[p<<1|1].sum=e[p].tag*Len(e[p<<1|1]);
e[p<<1].tag=e[p].tag;e[p<<1|1].tag=e[p].tag;
e[p].tag=-1;
}
void pushup(int p){
e[p].sum=e[p<<1].sum+e[p<<1|1].sum;
}
int Query(int p,int x,int y)
{
int l=e[p].l,r=e[p].r,mid=l+r>>1;
if(l==x&&y==r)
return e[p].sum;
if(e[p].tag!=-1) pushdown(p);
if(y<=mid) return Query(p<<1,x,y);
if(x>mid) return Query(p<<1|1,x,y);
return Query(p<<1,x,mid)+Query(p<<1|1,mid+1,y);
}
void Update(int p,int x,int y,int z)
{
int l=e[p].l,r=e[p].r,mid=l+r>>1;
if(l==x&&y==r)
{
e[p].sum=Len(e[p])*z;
e[p].tag=z;return;
}
if(y<=mid) Update(p<<1,x,y,z);
else if(x>mid) Update(p<<1|1,x,y,z);
else Update(p<<1,x,mid,z),Update(p<<1|1,mid+1,y,z);
pushup(p);
}
void Install(int x)
{
int fx=top[x],ans=deep[x]+1;
while(fx!=1)
{
ans-=Query(1,pos[fx],pos[x]);
Update(1,pos[fx],pos[x],1);
x=fa[fx],fx=top[x];
}
ans-=Query(1,1,pos[x]);
Update(1,1,pos[x],1);
printf("%d\n",ans);
}
void Uninstall(int x)
{
printf("%d\n",Query(1,pos[x],pos[x]+sz[x]-1));
Update(1,pos[x],pos[x]+sz[x]-1,0);
}
int main()
{
//freopen("D:\\oi\\in.txt","r",stdin);
n=read();
for(int i=2;i<=n;i++) Add(fa[i]=read()+1,i);
Dfs(1);dfs(1,1);Build(1,1,n);
m=read();
for(int i=1;i<=m;i++)
{
char ch[10];static int x;
scanf("%s",ch);x=read()+1;
if(ch[0]=='i') Install(x);
else Uninstall(x);
}
return 0;
}
T3
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define N 100005
const int Lim=255;
using namespace std;
typedef long long ll;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,mod;
ll ans;
int p[]={2,3,5,7,11,13,17,19};
ll f[260][260],g[2][260][260];
class Digit{
public:
int S,Big;
}e[501];
bool operator <(Digit a,Digit b){
return a.Big<b.Big;
}
int main()
{
n=read(),mod=read();
for(int i=2,x;i<=n;i++)
{
x=i;
for(int j=0;j<8;j++)
{
if(i%p[j]>0) continue;
e[i].S|=(1<<j);
while(x%p[j]==0) x/=p[j];
}
e[i].Big=x;
}
sort(e+2,e+1+n);f[0][0]=1;
for(int i=2;i<=n;i++)
{
if(i==2||e[i].Big!=e[i-1].Big||e[i].Big==1)
{
memcpy(g[0],f,sizeof(g[0]));
memcpy(g[1],f,sizeof(g[1]));
}
for(int j=Lim;~j;j--)
{
for(int k=Lim;~k;k--)
{
if((j&k)>0) continue;
if((e[i].S&k)==0)
g[0][j|e[i].S][k]+=g[0][j][k],g[0][j|e[i].S][k]%=mod;
if((e[i].S&j)==0)
g[1][j][k|e[i].S]+=g[1][j][k],g[1][j][k|e[i].S]%=mod;
}
}
if(i==n||e[i].Big==1||e[i].Big!=e[i+1].Big)
{
for(int j=Lim;~j;j--)
for(int k=Lim;~k;k--)
{
if((j&k)>0) continue;
f[j][k]=(g[0][j][k]+g[1][j][k]-f[j][k]);
}
}
}
for(int i=0;i<=Lim;i++)
for(int j=0;j<=Lim;j++)
if((i&j)==0)
ans=(ans+f[i][j])%mod;
ans=(ans+mod)%mod;
printf("%lld\n",ans);
return 0;
}