题解:
\(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));
}
题解:
注意到,一个数大于\(\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);
}
}
题解:
打表找规律,乱搞,以下附上出题人的证明过程;
\(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();
}
}