prime ——3784
思路:筛一筛质数,再将质数的倍数判一下,前缀和维护,然而这样就卡过去了…当然,正解无非就是更强大的筛法——线性筛。然而,老司机(小c)还有一种做法:将一个数除以其最大质因子,再判断商的最大质因子是否为本身这样似乎不用线性筛就更快了…那么我就将二者结合一下。
#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define LL long long
#define N 10000005
using namespace std;
int Q,L,R;
int sum[N];
int mark[N],p[N],cnt;
void Init(){
mark[1]=1;
REP(i,2,N){
if(!mark[i])p[cnt++]=mark[i]=i;
REP(j,0,cnt){
LL x=1ll*p[j]*i;
if(x>=N)break;
mark[x]=p[j];
if(!(i%p[j]))break;
}
}
REP(i,2,N){
int x=i/mark[i];
sum[i]=sum[i-1]+(mark[x]==x);
}
}
int main(){
// freopen("prime.in","r",stdin);
// freopen("prime.out","w",stdout);
Init();
scanf("%d",&Q);
while(Q--){
scanf("%d%d",&L,&R);
printf("%d\n",sum[R]-sum[L-1]);
}
return 0;
}
room ——3785
思路:bfs,不解释了,太明显了…But今天一开始切分(求稳),结果切着切着分就少了(tm着样例太水了)…However,这里要状压,常数有点大吧
#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define LL long long
#define INF 0x3f3f3f3f
#define N 10005
#define M 10005
#define K 15
using namespace std;
int n,m,k;
struct P30{
int d[105][505];
void solve(){
memset(d,INF,sizeof(d));
REP(i,1,m){
int a,b;
scanf("%d%d",&a,&b);
d[a][b]=1;
}
d[1][1]=0;
REP(l,1,n){
REP(i,1,n){
if(i==k)continue;
REP(j,1,n){
if(i==j || j==k)continue;
d[i][j]=min(d[i][j],d[i][l]+d[l][j]);
}
}
}
if(d[1][n]==INF)puts("No Solution");
else printf("%d\n",d[1][n]);
}
}p30;
struct P50{
int d[N];
struct node{
int from,to;
}es[M];
void Bellman(){
memset(d,INF,sizeof(d));
d[1]=0;
while(1){
bool f=0;
REP(i,1,m)if(d[es[i].from]!=INF && d[es[i].to]>d[es[i].from]+1)f=1,d[es[i].to]=d[es[i].from]+1;
if(!f)break;
}
}
void solve(){
REP(i,1,m)scanf("%d%d",&es[i].from,&es[i].to);
Bellman();
if(d[n]==INF)puts("No Solution");
else printf("%d\n",d[n]);
}
}p50;
struct P100{
int get[N],vis[N][1<<11];
struct edge{
int to,mark;
};
vector<edge>E[M];
struct node{
int step,x,used;
};
queue<node>Q;
void bfs(){
Q.push((node){0,1,get[1]});
while(!Q.empty()){
node now=Q.front();Q.pop();
if(now.x==n){
printf("%d\n",now.step);
exit(0);
}
REP(i,0,E[now.x].size()-1){
edge y=E[now.x][i];
if((now.used|y.mark)!=now.used)continue;
node nxt;
nxt.x=y.to;
nxt.step=now.step+1;
nxt.used=now.used|get[y.to];
if(vis[nxt.x][nxt.used])continue;
vis[nxt.x][nxt.used]=nxt.step;
Q.push(nxt);
}
}
}
void solve(){
REP(i,1,n){
int f;
get[i]=0;
REP(j,0,k-1){
scanf("%d",&f);
if(f)get[i]|=1<<j;
}
}
REP(i,1,m){
int a,b,f;
scanf("%d%d",&a,&b);
edge tmp;
tmp.to=b;
tmp.mark=0;
REP(j,0,k-1){
scanf("%d",&f);
if(f)tmp.mark|=1<<j;
}
E[a].push_back(tmp);
}
bfs();
puts("No Solution");
}
}p100;
int main(){
// freopen("room.in","r",stdin);
// freopen("room.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
if(!k && n<=100)p30.solve();
else if(!k && n<=1000)p50.solve();
else p100.solve();
return 0;
}
light ——3786
思路:题意简单明了,就是求树上的两条路径的的重复的点,而且这里两点路径分别为a->b,c->b,那就更显然了,求出两两之间的lca分类讨论一下就出来了,这里分类讨论也是出奇的少,总而言之判一下路径是否覆盖——即a与b的lca和b与c的lca相等时,反之…
#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define INF 0x3f3f3f3f
#define N 200005
#define S 20
using namespace std;
int n,Q,num;
vector<int>E[N];
int D[N],fa[S][N];
struct PList{
int Dx;
void dfs(int x,int f){
D[x]=D[f]+1;
REP(i,0,E[x].size()-1){
int y=E[x][i];
if(y==f)continue;
dfs(y,x);
}
}
void solve(){
REP(i,1,n)if(E[i].size()<2)Dx=i;
dfs(Dx,0);
REP(i,1,Q){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(D[a]>=D[b] && D[c]>=D[b])printf("%d\n",min(D[a],D[c])-D[b]+1);
else if(D[a]<=D[b] && D[c]<=D[b])printf("%d\n",D[b]-max(D[a],D[c])+1);
else puts("1");
}
}
}p_list;
struct P100{
void Up(int &x,int step){
DREP(i,S-1,0)if(step&(1<<i))x=fa[i][x];
}
int Lca(int a,int b){
if(D[a]>D[b])swap(a,b);
Up(b,D[b]-D[a]);
if(a==b)return a;
DREP(i,S-1,0)if(fa[i][a]!=fa[i][b])a=fa[i][a],b=fa[i][b];
return fa[0][a];
}
void Init(){
REP(j,1,S-1)
REP(i,1,n)
fa[j][i]=fa[j-1][fa[j-1][i]];
}
void dfs(int x,int f){
D[x]=D[f]+1;
fa[0][x]=f;
REP(i,0,E[x].size()-1){
int y=E[x][i];
if(y==f)continue;
dfs(y,x);
}
}
void solve(){
dfs(1,0);
Init();
REP(i,1,Q){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int lca1=Lca(a,b),lca2=Lca(b,c),lca3=Lca(a,c);
printf("%d\n",lca1==lca2?D[lca3]-2*D[lca1]+D[b]+1:D[b]-max(D[lca1],D[lca2])+1);
}
}
}p100;
int main(){
// freopen("light.in","r",stdin);
// freopen("light.out","w",stdout);
scanf("%d%d%d",&n,&Q,&num);
REP(i,1,n-1){
int a,b;
scanf("%d%d",&a,&b);
E[a].push_back(b);
E[b].push_back(a);
}
if(num>=11 && num<=13 || num>=17 && num<=18)p_list.solve();
else p100.solve();
return 0;
}
小结:今天的题比较水,但是该ak的还是没有,切分还是不熟练吧(暴力敲太快了,cost打成to…)。