测试 6
思路:将每个联通块的贡献乘起来就是答案
如果一个联通块的边数>点数 ,那么无解
如果边数=点数,那么贡献是 2
如果边数=点数-1,那么贡献是点数
#include<queue> #include<cstdio> #include<iostream> #define N 100001 #define mod 1000000007 using namespace std; int front[N],to[N*2],nxt[N*2],tot; bool vis[N]; int d[N]; queue<int>q; int ans=1; void add(int u,int v){ to[++tot]=v;nxt[tot]=front[u];front[u]=tot; to[++tot]=u;nxt[tot]=front[v];front[v]=tot; d[v]++; } bool bfs(int s){ while(!q.empty()) q.pop(); int p=0,e=0; q.push(s); vis[s]=true; while(!q.empty()){ int now=q.front(); q.pop(); p++; e+=d[now]; for(int i=front[now];i;i=nxt[i]) if(!vis[to[i]]){ vis[to[i]]=true; q.push(to[i]); } } if(e>p) return false; if(e==p) ans=ans*2%mod; else ans=1ll*ans*p%mod; return true; } int main(){ freopen("girl.in","r",stdin); freopen("girl.out","w",stdout); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); } for(int i=1;i<=n;i++) if(!vis[i]) if(!bfs(i)){ cout<<0; return 0; } cout<<ans; return 0; }
显然的结论:
若一个数的K进制和-k进制相同
那么他的k进制/-k进制的偶数位一定是0
然后乱搞就好了
也可以数位DP
#include<cmath> #include<cstdio> #include<iostream> using namespace std; int k,len; int a[67]; long long n,ans; long long bit[67]; int main(){ freopen("endless.in","r",stdin); freopen("endless.out","w",stdout); scanf("%I64d%d",&n,&k); while(n){ a[++len]=n%k; n/=k; } if(!(len&1)){ ans=pow(1LL*k,len/2); cout<<ans; } else{ for(int i=len;i>=1;i--) if(a[i]){ if(!(i&1)){ ans+=pow(1LL*k,i/2); break; } ans+=1LL*a[i]*pow(1LL*k,i/2); if(i==1) ans++; } cout<<ans; } }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。