HDU 6285 (圖論+計數)
阿新 • • 發佈:2019-01-09
題意:
在一個n個點的完全圖中,第i個點的權值為2^i,選擇一些邊,需要選擇一些點使得所有邊至少有一個端點被覆蓋,同時權值之和最小。
在上述情況下,給出選擇的點的權值和,問有多少種選擇邊的方案符合這種選點。
思路:
按照權值從大到小列舉每個點,當一個點被選中時,因為貪心的做法,這個點一定是某一條邊中的權值較小的點。
所以這個點至少和之前沒有選擇的點中的一個有一條邊,即有(2^(cnt0))-1種方案,(2^(cnt0))是每個沒有選中的點可以連邊和不連邊,-1是減去了全部都不連的情況。
同時,這個選中的點可以和權值比它小的點任意連邊,即有(2^(i-1))種方案。
每種方案的乘積就是種的方案數。
程式碼:
#include <iostream> #include <iomanip> #include <algorithm> #include <cstring> #include <cctype> #include <cstdlib> #include <cstdio> #include <cmath> #include <ctime> #include <map> #include <list> #include <set> #include <stack> #include <queue> #include <string> #include <sstream> #define pb push_back #define X first #define Y second #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define pii pair<int,int> #define qclear(a) while(!a.empty())a.pop(); #define lowbit(x) (x&-x) #define sd(n) scanf("%d",&n) #define sdd(n,m) scanf("%d%d",&n,&m) #define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k) #define mst(a,b) memset(a,b,sizeof(a)) #define cout3(x,y,z) cout<<x<<" "<<y<<" "<<z<<endl #define cout2(x,y) cout<<x<<" "<<y<<endl #define cout1(x) cout<<x<<endl #define IOS std::ios::sync_with_stdio(false) #define SRAND srand((unsigned int)(time(0))) typedef long long ll; typedef unsigned long long ull; typedef unsigned int uint; using namespace std; const double PI=acos(-1.0); const int INF=0x3f3f3f3f; const ll mod=1e9+7; const double eps=1e-8; const int maxn=100005; const int maxm=10005; int n; char str[maxn]; ll pre[maxn]; void solve() { pre[0]=1; for(int i=1;i<maxn;i++){ pre[i]=(pre[i-1]<<1)%mod; } while(~sd(n)) { scanf("%s",str); int len=strlen(str); ll ans=1; int cnt=0; int lim=len>>1; for(int i=0;i<lim;i++){ swap(str[i],str[len-i-1]); } for(int i=n-1;i>=0;i--){ if(i>=len||str[i]=='0'){ cnt++; }else{ ans=ans*(pre[cnt]-1+mod)%mod*pre[i]%mod; } } printf("%lld\n",ans); } return ; } int main() { #ifdef LOCAL freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #else // freopen("","r",stdin); // freopen("","w",stdout); #endif solve(); return 0; }