10.27night清北刷题班

/*
枚举每个部分的总和,利用前缀和进行检验。
如果能分成4部分就一定能分成2部分,就筛了一边素数优化。
清空数组!!!
*/ #include<bits/stdc++.h> #define N 1000001 using namespace std; int prime[N],no[N]={0,1},num[N],sum[N]; int n,m,tot,cur,tmp,flag; char s[N]; bool vis[N]; void pri() { for(int i=2;i<=N;i++) { if(!no[i]) prime[++tot]=i; for(int j=1;j<=tot;j++) { if(i*prime[j]>=N)break; no[i*prime[j]]=1; if(i%prime[j]==0) break; } } } int main() { freopen("divie.in","r",stdin); freopen("divide.out","w",stdout); int T;scanf("%d",&T); pri(); while(T--) { scanf("%s",s+1); n=strlen(s+1);int opt=0; memset(num,0,sizeof num); memset(sum,0,sizeof sum); memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) num[i]=s[i]-'0'; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+num[i],vis[sum[i]]=1; if(sum[n]==0) {printf("YES ");continue;} for(int i=1;i<=min(n,tot);i++) { if(prime[i]>sum[n]) break; if(sum[n]%prime[i]) continue; cur=prime[i];tmp=sum[n]/prime[i]; flag=0; for(int j=1;j<=cur;j++) if(!vis[j*tmp]){flag=1;break;} if(!flag) {opt=1;printf("YES ");break;} } if(opt) continue; printf("NO "); } return 0; }

/*
dp[n]表示n个点,每个点都和点1相连,且n个点互相连通的图的个数。
S[n]总的个数
g[n]表示n个点,每个点都和点1相连,且不是n个点互相连通的图的个数。
考虑从除了1之外的n-1个点中选出i-1个点,让这i个点互相连通,而剩下的n-i个点和这i个点没有边相连,互相之间随意连接。
这个代码5000要跑1.6s,所以后面90%数据打表23333
100%需要fft优化。
*/
#include<bits/stdc++.h>

#define N 50001
#define ll long long
#define M 998244353

using namespace std;
ll fac[N]={1,1},inv[N]={1,1},f[N]={1,1};
ll dp[N],g[N],S[N];
int n;

ll C(ll a,ll b)
{
    return fac[a]*inv[b]%M*inv[a-b]%M;
}

ll kfc(ll x,ll y)
{
    x=x%M,y=y%M;
    return ((x*y-(ll)(((long double)x*y+0.5)/M)*M)%M+M)%M;
}

ll ksm(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=kfc(res,a)%M;
        b>>=1; a=kfc(a,a)%M;
    }return res%M;
}

void init()
{
    for(int i=2;i<N;i++)
    {
        fac[i]=fac[i-1]*i%M;
        f[i]=(M-M/i)*f[M%i]%M;
        inv[i]=inv[i-1]*f[i]%M;
    }
}

int main()
{
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    cin>>n;init();
    dp[1]=1;g[1]=0;
    for(int i=1;i<=5000;i++) S[i]=ksm(2,(i*(i-1))/2);
    for(int i=2;i<=5000;i++)
    {
        g[i]=0;
        for(int j=1;j<i;j++)
            g[i] =(g[i]+(C(i-1,j-1)*dp[j]%M*S[i-j])%M)%M; 
        dp[i]=(S[i]-g[i]+M)%M;
    }
    cout<<dp[n]<<endl;
    return 0;
}

/*
暴力枚举选哪几条路径
*/
#include<bits/stdc++.h>

#define N 100007
#define ll long long

using namespace std;
ll n,m,ans,cnt,flag,cur;
ll head[N],deep[N],sum[N],f[N][28];
ll vis[N],choose[N],W[N];
struct edge{
    ll u,v,net;
}e[N<<1];
struct node{
    int pos,x,y;
}p[N];

inline ll read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline ll max(ll a,ll b){return a>b?a:b;}

inline void add(int u,int v)
{
    e[++cnt].v=v;e[cnt].net=head[u];head[u]=cnt;
}

void DFS(int u,int fa,int c)
{
    f[u][0]=fa;deep[u]=c;
    for(int i=head[u];i;i=e[i].net)
    {
        int v=e[i].v;
        if(v==fa) continue;
        sum[v]+=sum[u];
        DFS(v,u,c+1);
    }
}

void get()
{
    for(int j=1;j<=27;j++) for(int i=1;i<=n;i++)
    f[i][j]=f[f[i][j-1]][j-1];
}

int lca(int a,int b)
{
    if(deep[a]<deep[b]) swap(a,b);
    int t=deep[a]-deep[b];
    for(int i=0;i<=26;i++)
     if(t&(1<<i)) a=f[a][i];
      if(a==b) return a;
    for(int i=26;i>=0;i--)
      if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i];
    return f[a][0];
}

ll S(ll a,ll b)
{
    int res=lca(a,b);
    return sum[a]+sum[b]-2*sum[res]+W[res];
}

void expand(int i)
{
    int x=p[i].x,y=p[i].y,res=lca(x,y);
    if(vis[res]) {flag=1;return;}
    while(x!=res)
    {
        if(vis[x])
        {flag=1;break;}
          vis[x]=1;x=f[x][0];
    }
    while(y!=res){if(vis[y]){vis[y]=2;flag=1;}else vis[y]=1;y=f[y][0];}vis[res]=1;
}

void clear(int i)
{
    int x=p[i].x,y=p[i].y,res=lca(x,y);
    if(x==res && vis[x]) vis[x]--;
    if(y==res && vis[y]) vis[y]--; 
    while(x!=res){vis[x]=0;x=f[x][0];}
    while(y!=res){if(vis[y])vis[y]--;y=f[y][0];}if(x!=res && y!=res)vis[res]--;    
}

void dfs(int k,int tot,int lim)
{
    if(tot==lim)
    {
        flag=0,cur=0;
        memset(vis,0,sizeof vis);
        for(int i=1;i<=m;i++)
        {
            if(choose[i])
            {
                expand(i);
                if(flag) return;
                else cur+=S(p[i].x,p[i].y);
            }
        }
        ans=max(ans,cur);
        return;
    }
    for(int i=k;i<=m;i++)
    {
        if(choose[i]) continue;
        choose[i]=1;dfs(i+1,tot+1,lim);
        choose[i]=0;
        clear(i);
    }
}

int main() 
{
    freopen("ly.in","r",stdin);
    int x,y;
    n=read();
    for(int i=1;i<=n;i++) W[i]=sum[i]=read();
    for(int i=1;i<n;i++)
    {
        x=read();y=read();
        add(x,y);add(y,x);
    }
    DFS(1,1,0);get();
    m=read();
    for(int i=1;i<=m;i++)
    {
        p[i].x=read();p[i].y=read();p[i].pos=i;
        ans=max(ans,S(p[i].x,p[i].y));
    }
    for(int i=1;i<=n/2;i++)
    {
        memset(choose,0,sizeof choose);
        memset(vis,0,sizeof vis);
        dfs(1,0,i);
    }
    printf("%lld
",ans);
    return 0;
}
/*
10
1 2 3 4 5 6 7 8 9 10
10 6
9 6
3 1
6 7
6 3
3 8
8 5
8 4
2 6
4
2 3
3 4
4 5
9 1

*/
30暴力
原文地址:https://www.cnblogs.com/L-Memory/p/9867408.html