2018.10.26 练习赛

T1 【NOIP2017模拟】建设图

题解:

\(Tarjan\)缩点把原图处理为一颗树,找树上度数为一的点,统计答案(原理同昨日\(T3\),统计出点数为\(ans\),贪心连边,点数为奇数多连一条即可,\((ans>>1)+(ans\&1))\)

\(code\):

#include<cstdio> 
#include<iostream> 
#include<algorithm> 
#include<ctype.h>  
#include<vector> 
#include<queue> 
#include<cstring> 
#include<map> 
#include<cmath> 
#include<stdlib.h> 
#include<ctime> 
#include<stack>
#define lowbit(x) (x&-x) 
#define ll long long 
#define ld double 
#define mod 998244353  
using namespace std; 

char buf[1<<20],*p1,*p2; 
inline char gc() 
{ 
    return getchar(); 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; 
} 

template<typename T> 
inline void read(T &x) 
{ 
    char tt; 
    bool flag=0; 
    while(!isdigit(tt=gc())&&tt!='-'); 
    tt=='-'?(flag=1,x=0):(x=tt-'0'); 
    while(isdigit(tt=gc())) x=x*10+tt-'0'; 
    if(flag) x=-x; 
}

const int maxn=100002;
int n,m,tot;
vector<int>G[maxn];
int dfn[maxn],low[maxn],scc,deg[maxn],belong[maxn];
stack<int>s;
bool instack[maxn];

void dfs(int x,int pre)
{
    dfn[x]=low[x]=++tot;
    s.push(x),instack[x]=1;int p;
    for(int i=G[x].size()-1;i>=0;i--)
    {
        p=G[x][i];
        if(p==pre) continue;
        if(!dfn[p])
        {
            dfs(p,x);
            low[x]=min(low[x],low[p]);
        }
        else if(instack[p]&&dfn[p]) low[x]=min(low[x],low[p]);
    }
    if(dfn[x]==low[x])
    {
        scc++;
        do{
            p=s.top();s.pop();
            instack[p]=0;belong[p]=scc;
        }while(p!=x);
    }
}

int main()
{
//  freopen("graph.in","r",stdin);
//  freopen("graph.out","w",stdout);
    read(n),read(m);
    for(int i=1;i<=m;i++)
    {
        
        int x,y;
        read(x),read(y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs(1,0);
    for(int x=1;x<=n;x++)
    for(int i=G[x].size()-1;i>=0;i--)
    {
        int p=G[x][i];
        deg[belong[p]]+=belong[p]!=belong[x];
    }int ans=0;
    for(int i=1;i<=scc;i++) ans+=deg[i]==1;
    printf("%d",(ans>>1)+(ans&1));
}

T2【NOIP2017模拟】乘积

题解:

注意到,一个数大于\(\sqrt{N}\)的质因数个数小于等于一(本结论易证:若有两个及以上,其乘积会大于N),分组状压\(DP\)

\(\sqrt{500}\)以内的质数仅有\(8\)个,设定状态为\(F[i][j][s]\)表示前\(i\)个数中选择\(j\)个数,\(s\)为包含的质因数集合,朴素不优化空间复杂度\(O(N*K*256)\),会\(MLE\);

在背包实现时,可以将第一位滚掉处理,实现空间复杂度\(O(K*256)\);

\(code:\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<ctype.h> 
#include<vector>
#include<queue>
#include<cstring>
#include<map>
#include<cmath>
#include<stdlib.h>
#include<ctime>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
using namespace std;

const int mod=1e9+7;
char buf[1<<20],*p1,*p2;
inline char gc()
{
//    return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    bool flag=0;
    while(!isdigit(tt=gc())&&tt!='-');
    tt=='-'?(flag=1,x=0):(x=tt-'0');
    while(isdigit(tt=gc())) x=x*10+tt-'0';
    if(flag) x=-x;
}

inline int pow_(int a) {return a*a;}
inline int add(int a,int b) {return a+b<mod?a+b:a+b-mod;}

const int mx=(1<<8)-1;
const int maxn=502;

int t,n,k,temp[maxn];
int f[maxn][mx+1],w[maxn];
int pri[15]={0,2,3,5,7,11,13,17,19,21},a[maxn];
vector<int>G[maxn];

void sent()
{
    memset(f,0,sizeof(f));f[0][0]=1;
    for(int i=1;i<=n;i++) w[i]=0,a[i]=i,G[i].clear();
}

int main()
{
    read(t);
    while(t--)
    {
        read(n),read(k);sent();
        for(int i=1;i<=n;i++)
        for(int j=1;j<=8;j++)
        {
            if(a[i]%pow_(pri[j])==0) w[i]=-1;
            else if(a[i]%pri[j]==0) a[i]/=pri[j],w[i]|=(1<<(j-1));
        }
        
        for(int i=1;i<=n;i++)if(~w[i])
        if(a[i]==1) G[i].push_back(i);
        else G[a[i]].push_back(i);
        
        for(int x=1;x<=n;x++)
        {
            int siz=G[x].size();
            if(!siz) continue;
            for(int i=0;i<siz;i++) temp[i]=w[G[x][i]]; 
            for(int i=k-1;i>=0;i--)
            for(int j=0;j<siz;j++)              
            {
                int v=temp[j];
                for(int s=mx^v;;s=(s-1)&(v^mx))
                {
                    f[i+1][s|v]=add(f[i+1][s|v],f[i][s]);
                    if(!s) break;
                }
            }
        }
        
        ll ans=0;
        for(int i=1;i<=k;i++)
        for(int j=0;j<=mx;j++)
        ans=add(ans,f[i][j]);
        printf("%lld\n",ans);
    }
}

T3 【NOIP2017模拟】数学

题解:

打表找规律,乱搞,以下附上出题人的证明过程;

\(code:\)

#include<cstdio> 
#include<iostream> 
#include<algorithm> 
#include<ctype.h>  
#include<vector> 
#include<queue> 
#include<cstring> 
#include<map> 
#include<cmath> 
#include<stdlib.h> 
#include<ctime> 
#define lowbit(x) (x&-x) 
#define ll long long 
#define ld double 
using namespace std; 

char buf[1<<20],*p1,*p2; 
inline char gc() 
{ 
//    return getchar(); 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; 
} 

template<typename T> 
inline void read(T &x) 
{ 
    char tt; 
    bool flag=0; 
    while(!isdigit(tt=gc())&&tt!='-'); 
    tt=='-'?(flag=1,x=0):(x=tt-'0'); 
    while(isdigit(tt=gc())) x=x*10+tt-'0'; 
    if(flag) x=-x; 
}

ll t,a,n;
ll ans[30][30]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,3,5,6,10,10,18,18,34,34,66,66,130,130,258,258,514,514,1026,1026,2050,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,9,17,33,65,66,130,258,514,514,1026,2050,4098,4098,8194,16386,32770,32770,65538,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,32,64,127,255,511,1023,1025,2049,4097,8192,16383,32767,32768,65536,131072,262144,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,128,256,512,1024,2047,4095,8191,16383,16384,32768,65536,131072,262144,524288,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,511,1023,2046,4094,8190,16382,32765,65533,131069,262141,262144,524288,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,2048,4096,8192,16383,32766,65534,131070,262142,524286,1048574,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,8190,16382,32765,65533,131069,262141,524284,1048572,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32767,65535,131071,262143,524287,1048575,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131069,262141,524284,1048572,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,524287,1048575,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
ll pow_[32];
ll mg(ll ad,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans%pow_[n]*ad)%pow_[n];
        ad=(ad%pow_[n]*ad)%pow_[n];
        b>>=1;
    }
    return ans;
}

void sent()
{
    pow_[0]=1;
    for(int i=1;i<=31;i++) pow_[i]=pow_[i-1]<<1;
}

void solve1()
{
    if(ans[a-1][n-1])printf("%lld\n",ans[a-1][n-1]);
    else printf("%lld\n",33554432);
}

void solve2()
{
    for(ll i=1;i<=pow_[n];i++)
    if(mg(a,i)==mg(i,a))
    {printf("%lld\n",((pow_[n]-i)>>1)+1);break;}
}

int main()
{
    read(t);sent();
    while(t--)
    {
        read(a),read(n);
        if(a&1){puts("1");continue;}
        if(a<n) solve1();
        else solve2();
    }
}

猜你喜欢

转载自www.cnblogs.com/KatouKatou/p/9853784.html