oneman233

The Preliminary Contest for ICPC Asia Xuzhou 2019

小   银   川,给大爷们AK穿了

比赛地址:https://www.jisuanke.com/contest/3005?view=challenges

A、(待补)

B、1e9的数据范围,一开始从1到n的所有数字都有一个标记

q个询问,去掉某个数字上的标记,询问某个数字之后最靠近它的有标记的数字,保证n一直有标记,去除了无解的情况

用一个类似于动态分配的并查集,离线处理所有询问,首先给所有询问的点分配空间,每次给某个点打上标记就相当于把这个点与这个点加一合并

用了unordered_map加快读快写,甚至关了define int long long才卡过去

代码:

#include <bits/stdc++.h>
//#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=1000005;
//const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}
inline int read()
{
    char ch=getchar();int s=0,w=1;
    while(ch<48||ch>57){if(ch=='-')w=-1;ch=getchar();}
    while(ch>=48&&ch<=57){s=(s<<1)+(s<<3)+ch-48;ch=getchar();}
    return s*w;
}
inline void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+48);
}

int n,q,z[maxn],x[maxn];
unordered_map<int,int> fa;

int _find(int x){
    if(fa[x]==0){
        fa[x]=x;
        return x;
    }
    if(x!=fa[x]) fa[x]=_find(fa[x]);
    return fa[x];
}

signed main(){
    n=read(),q=read();
    re(i,1,q)
        z[i]=read(),x[i]=read(),fa[x[i]]=x[i];
    re(i,1,q){
        if(z[i]==1)
            fa[x[i]]=x[i]+1;
        else if(z[i]==2)
            write(_find(x[i])),prn();
    }
    return 0;
}

C、签到,但是因为题意不清被吐槽为工地英语

传世经典:and each part weighs two times as much as a kilogram

实际意思是切成两半,每一半都是偶数,特判一下2完事

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=500005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}

int n;

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n;
    if(n%2==0&&n!=2) cout<<"YES";
    else cout<<"NO";
    return 0;
}

D、题解写的kmp,被find过穿了,没构造的数据在find面前还是太弱了

题意是给你一个字符串s和t个字符串t,你需要判断他们的关系:

完全一样输出jntm!,长度相同但不一样输出friend!

t比s短并且t是s的子串输出my child!,否则输出oh, child!

t比s长并且s是t的子串输出my teacher!,否则输出senior!

这种输出题最好还是复制样例,不然连oh和child之间的空格都不一定看得见

判断s是不是t的子串套用if(t.find(s)!=t.npos)即可

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=500005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}

string s,t;
int q;

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>s;
    cin>>q;
    while(q--){
        cin>>t;
        if(s.length()==t.length()){
            if(s==t) cout<<"jntm!"<<endl;
            else cout<<"friend!"<<endl;
        }
        else if(s.length()>t.length()){
            if(s.find(t)!=s.npos) cout<<"my child!"<<endl;
            else cout<<"oh, child!"<<endl;
        }
        else{
            if(t.find(s)!=t.npos) cout<<"my teacher!"<<endl;
            else cout<<"senior!"<<endl;
        }
    }
    return 0;
}

E、(待补)

F、(待补)

G、关于回文自动机参见:http://www.mynameisdhr.com/%e5%9b%9e%e6%96%87%e8%87%aa%e5%8a%a8%e6%9c%ba/

题面是给你一个串,每个回文子串的贡献是当中出现的不同字符个数,统计所有子串的总贡献

回文自动机裸题,建出PAM之后dfs搜答案即可,注意对答案的贡献要乘以本质相同的回文串个数

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=500005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}

struct PAM{
int tot,last,n,cur;
int fail[maxn],len[maxn],cnt[maxn],son[maxn][26],num[maxn];
char s[maxn];
int get(int p,int x){while(s[x-len[p]-1]!=s[x])p=fail[p];return p;}
int newnode(int x){len[tot]=x;return tot++;}
void build(){
scanf("%s",s+1);
s[0]=-1,fail[0]=1,last=0;
newnode(0),newnode(-1);
for(n=1;s[n];++n){
s[n]-='a';
cur=get(last,n);
if(!son[cur][s[n]]){
int now=newnode(len[cur]+2);
fail[now]=son[get(fail[cur],n)][s[n]];
num[now]=num[fail[now]]+1;//
son[cur][s[n]]=now;
}
cnt[last=son[cur][s[n]]]++;
}
for(int i=tot-1;i>=0;--i)
cnt[fail[i]]+=cnt[i];
}
}pam;

int v[26],ans=0;

void dfs(int x,int k){
    if(pam.len[x]>0) ans+=k*pam.cnt[x];
    fo(i,0,26){
        if(pam.son[x][i]!=0){
            if(!v[i]){
                v[i]=1;
                dfs(pam.son[x][i],k+1);
                v[i]=0;
            }
            else dfs(pam.son[x][i],k);
        }
    }
}

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    pam.build();
    dfs(0,0);
    dfs(1,0);
    pr(ans);
    return 0;
}

H、(待补)

I、给你一个n(n<=1e5)个数字的排列,m个询问,询问在[l,r]区间中有多少个i<j使得min(p[i],p[j])=gcd(p[i],p[j])

条件化简一下实际上就是p[i]是p[j]的倍数或者p[j]是p[i]的倍数

考虑到n不太大,也许所有合法的(i,j)可以预先处理好,然后把询问离线,按照右端点大小进行排序,看看有多少个(i,j)落在询问的区间内

到这儿已经基本得到雏形了,一个稍加修改的二维偏序

可以维护关于左端点的权值树状数组,在保证右端点满足大小关系的情况下在左端点位置加一

跟cdq分治不同的是,本题不需要在每次更换询问的时候清空树状数组

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
inline int read()
{
    char ch=getchar();int s=0,w=1;
    while(ch<48||ch>57){if(ch=='-')w=-1;ch=getchar();}
    while(ch>=48&&ch<=57){s=(s<<1)+(s<<3)+ch-48;ch=getchar();}
    return s*w;
}
inline void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+48);
}
//
int n,m,l,r,p[maxn],rp[maxn],ans[maxn];
struct node{
    int l,r;
    node(int L,int R):l(L),r(R){}
    bool operator < (const node& o)const{
        if(r!=o.r) return r<o.r;
        else return l<o.l;
    }
};
struct query{
    int l,r,id;
    query(int L,int R,int I):l(L),r(R),id(I){}
    bool operator < (const query& o)const{
        if(r!=o.r) return r<o.r;
        else return l<o.l;
    }
};
vector<node> pir;
vector<query> ask;
//
int tr[maxn];
inline int lowbit(int x){return x&-x;}
inline void add(int x,int y){
    for(;x<=n;x+=lowbit(x)) tr[x]+=y;
}
inline int sum(int x){
    int res=0;
    for(;x>0;x-=lowbit(x)) res+=tr[x];
    return res; 
}

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;++i)
        p[i]=read(),rp[p[i]]=i;
    for(int i=1;i<=n;++i){
        int cnt=2;
        while(p[i]*cnt<=n){
            pir.push_back(node(min(i,rp[p[i]*cnt]),max(i,rp[p[i]*cnt])));
            cnt++;
        }
    }
    sort(pir.begin(),pir.end());
//    for(int i=0;i<pir.size();++i) cout<<pir[i].l<<' '<<pir[i].r<<endl;
    for(int i=1;i<=m;++i){
        l=read(),r=read();
        ask.push_back(query(l,r,i));
    }
    sort(ask.begin(),ask.end());
    int tmp=0;
    for(int i=0;i<ask.size();++i){
        while(pir[tmp].r<=ask[i].r&&tmp<pir.size()){
//            cout<<pir[tmp].l<<' '<<pir[tmp].r<<endl;
            add(pir[tmp].l,1);
            tmp++;
        }
        ans[ask[i].id]=sum(n)-sum(ask[i].l-1);
    }
    for(int i=1;i<=m;++i)
        write(ans[i]),printf("\n");
    return 0;
}
/*
6 3
1 5 6 2 4 3
3 5
2 3
1 3
*/

J、一棵树,默认1为树根

假设当前节点x有k个孩子,那么会在该节点等概率地选择k次,每次选择一个孩子继续dfs,每次dfs都更新最大树高,问你最后正确得到树高的概率是多少

答案以逆元形式输出一个分数即可

考虑树形dp向上转移,不为最大深度的叶子节点概率为0,为最大深度的叶子节点概率为1

一次选择中每个孩子被选中的概率是1/k,选择k次,一开始我以为选择k次是假的,果然WA了

实际上应该考虑在某一次选择中走不到正确位置的概率,为:

sigma((1-dp[son])/k)

那么k次选择之后走不到的概率就是上式的k次方,最后走到的概率就用1减去走不到的概率即可。

注意对于1减去一个大逆元,可以用1减去大逆元再加上模数的方式

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=1000005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=1000000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}

int n,x,y;
vei tr[maxn];
int dep[maxn],mx=-inf;
int dp[maxn];

void dfs1(int x,int f){
    dep[x]=dep[f]+1;
    mx=max(mx,dep[x]);
    fo(i,0,tr[x].size()){
        if(tr[x][i]!=f)
            dfs1(tr[x][i],x);
    }
}

void dfs2(int x,int f){
    int k=0,sum=0;
    fo(i,0,tr[x].size()){
        if(tr[x][i]!=f) k++;
    }
    fo(i,0,tr[x].size()){
        if(tr[x][i]!=f){
            dfs2(tr[x][i],x);
            sum+=(1-dp[tr[x][i]]+MOD)%MOD,sum%=MOD;
        }
    }
    sum=sum*qpow(k,MOD-2)%MOD;
    sum=qpow(sum,k)%MOD;
    if(k==0&&dep[x]==mx)
        dp[x]=1;
    else if(k==0&&dep[x]!=mx)
        dp[x]=0;
    else
        dp[x]=(1-sum+MOD)%MOD;
}

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    sc(n);
    re(i,1,n-1) scc(x,y),tr[x].pub(y),tr[y].pub(x);
    dfs1(1,1);
    dfs2(1,1);
    pr(dp[1]);
    return 0;
}

K、给你至多1000个点的集合,你需要找到一个中心点并且加入一些点,使得所有点的对称点都在集合中

你只需要找到最少需要加入的点数,而不需要找到那个中心点。

由于点数较少,考虑n方枚举,首先猜测一个结论,答案构成的中心点一定在某两点的对称中心上,这样才能最小化加入的点数

那么枚举所有两个点,利用map存储它们的中心点出现的次数,答案就是n-最多中心点出现的次数

考虑到n方枚举实际上把每个点对枚举了两次,所以用map维护的时候每次只需要加一即可

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=500005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}

int n;
int x[maxn],y[maxn];
mpii cnt;

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    sc(n);
    re(i,1,n) scc(x[i],y[i]),x[i]*=10,y[i]*=10;
    int mx=-inf;
    re(i,1,n){
        re(j,1,n){
            cnt[(x[i]+x[j])/2*10000000+(y[i]+y[j])/2]++;
            mx=max(mx,cnt[(x[i]+x[j])/2*10000000+(y[i]+y[j])/2]);
        }
    }
    pr(n-mx);
    return 0;
}

L、(待补)

M、(待补)

posted on 2019-09-07 21:54  oneman233  阅读(180)  评论(0)    收藏  举报

导航