测试 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;
    }
}

 

posted @ 2017-11-06 09:51  一蓑烟雨任生平  阅读(142)  评论(0编辑  收藏  举报