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();
	}
}
posted @ 2018-10-26 00:52  Katoumegumi  阅读(115)  评论(0编辑  收藏  举报
返回顶部