2020夏休み杭電第三場1005+1009そして調査集+数学
37816 ワード
1005 Little W and Contest
タイトル
http://acm.hdu.edu.cn/showproblem.php?pid=6795
に言及
n個の点が与えられ、2つの点があり、重み値はそれぞれ1と2であり、
最初はn個の点が互いにつながっていなかった.最初はn個の点が互いにつながっていなかった.最初はn個の点が互いにつながっていなかった.
次にn−1辺を加え,毎回加わる辺の2つの端点が事前に連通していないことを保証する.
3つのポイントを選択するには、3つのポイントの重み値の和が5以上で、3つのポイントが互いに接続されていない場合に、異なる選択スキームの数を計算します.
エッジを追加するたびに、現在の連通状態で異なる選択スキームの数が出力されます.
問題解
初期状態の計算:重み値が1の点の数がcnt 1、重み値が2の点の数がcnt 2であると仮定し、
このときの異なるスキームの総数:ans=C 2 cnt 2 x C 1 cnt 1+C 3 cnt 2
エッジを追加するたびに、どの部分のシナリオが非合法なシナリオになるかを考えています.
エッジマージのたびに2つの連通ブロックが動作するため、uとvの間にエッジが追加されると仮定する.
そこで、n個の点を、uが存在する連通ブロックGu、vが存在する連通ブロックGv、その他の残点Grの3つの部分に分けた.
非合法な案は以下の4種類ある.
(1)Guは重み値が1の点を選択し,Gvは重み値が2の点を選択し,Grは重み値が2の点を選択する.
(2)Guは重み値2の点を選択し,Gvは重み値1の点を選択し,Grは重み値2の点を選択する.
(3)Guは重み値2の点を選択し,Gvは重み値2の点を選択し,Grは重み値2の点を選択する.
(4)Guは重み値2の点を選択し,Gvは重み値2の点を選択し,Grは重み値1の点を選択する.
参考ブログ:https://blog.csdn.net/njuptACMcxk/article/details/107641773
ACコード
1009 Parentheses Matching
タイトル:
http://acm.hdu.edu.cn/showproblem.php?pid=6799
に言及
文字列sには、()*の3つの文字が含まれます.*を左右のカッコに変換するか、変換しないことができます.sカッコマッチングに適合する場合、最小の辞書順を求めて出力する.答えが出ない「No solution!」
問題解
優先的に左から星を左かっこに変更し、右かっこのマッチングを完了します.右から星を右かっこに変更し、左かっこのマッチングを完了します.これで辞書順が最小になります.
コード#コード#
タイトル
http://acm.hdu.edu.cn/showproblem.php?pid=6795
に言及
n個の点が与えられ、2つの点があり、重み値はそれぞれ1と2であり、
最初はn個の点が互いにつながっていなかった.最初はn個の点が互いにつながっていなかった.最初はn個の点が互いにつながっていなかった.
次にn−1辺を加え,毎回加わる辺の2つの端点が事前に連通していないことを保証する.
3つのポイントを選択するには、3つのポイントの重み値の和が5以上で、3つのポイントが互いに接続されていない場合に、異なる選択スキームの数を計算します.
エッジを追加するたびに、現在の連通状態で異なる選択スキームの数が出力されます.
問題解
初期状態の計算:重み値が1の点の数がcnt 1、重み値が2の点の数がcnt 2であると仮定し、
このときの異なるスキームの総数:ans=C 2 cnt 2 x C 1 cnt 1+C 3 cnt 2
エッジを追加するたびに、どの部分のシナリオが非合法なシナリオになるかを考えています.
エッジマージのたびに2つの連通ブロックが動作するため、uとvの間にエッジが追加されると仮定する.
そこで、n個の点を、uが存在する連通ブロックGu、vが存在する連通ブロックGv、その他の残点Grの3つの部分に分けた.
非合法な案は以下の4種類ある.
(1)Guは重み値が1の点を選択し,Gvは重み値が2の点を選択し,Grは重み値が2の点を選択する.
(2)Guは重み値2の点を選択し,Gvは重み値1の点を選択し,Grは重み値2の点を選択する.
(3)Guは重み値2の点を選択し,Gvは重み値2の点を選択し,Grは重み値2の点を選択する.
(4)Guは重み値2の点を選択し,Gvは重み値2の点を選択し,Grは重み値1の点を選択する.
参考ブログ:https://blog.csdn.net/njuptACMcxk/article/details/107641773
ACコード
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int N=1e5+10, mod=1e9+7;
int T,n;
int w[N];
int cnt[3];
int p[N];
int p1[N],p2[N];
int Find(int x)
{
if(p[x]!=x) p[x]=Find(p[x]);
return p[x];
}
int C_2(int n)
{
if(n<2) return 0;
return (ll)(n-1)*n/2%mod;
}
int C_3(int n)
{
if(n<3) return 0;
return (ll)(n)*(n-1)*(n-2)/6%mod;
}
int main()
{
cin>>T;
while(T--)
{
scanf("%d",&n);
memset(cnt,0,sizeof cnt);
for(int i=1;i<=n;i++)
{
scanf("%d",&w[i]);p[i]=i;
if(w[i]==1) {p1[i]=1, p2[i]=0;cnt[1]++;}
else {p2[i]=1, p1[i]=0;cnt[2]++;}
}
int ans=(C_3(cnt[2])+(ll)C_2(cnt[2])*cnt[1]%mod)%mod;
printf("%d
",ans);
int u,v;
for(int i=0;i<n-1;i++)
{
int k=0;
scanf("%d%d",&u,&v);
int pu=Find(u), pv=Find(v);
k=(k+(ll)p1[pu]*p2[pv]*(cnt[2]-p2[pu]-p2[pv]))%mod;
k=(k+(ll)p2[pu]*p1[pv]*(cnt[2]-p2[pu]-p2[pv]))%mod;
k=(k+(ll)p2[pu]*p2[pv]*(cnt[2]-p2[pu]-p2[pv]))%mod;
k=(k+(ll)p2[pu]*p2[pv]*(cnt[1]-p1[pu]-p1[pv]))%mod;
ans=(ans-k+mod)%mod;
printf("%d
",ans);
p[pv]=pu;
p1[pu]+=p1[pv], p2[pu]+=p2[pv];
p1[pv]=0, p2[pv]=0;
}
}
return 0;
}
1009 Parentheses Matching
タイトル:
http://acm.hdu.edu.cn/showproblem.php?pid=6799
に言及
文字列sには、()*の3つの文字が含まれます.*を左右のカッコに変換するか、変換しないことができます.sカッコマッチングに適合する場合、最小の辞書順を求めて出力する.答えが出ない「No solution!」
問題解
優先的に左から星を左かっこに変更し、右かっこのマッチングを完了します.右から星を右かっこに変更し、左かっこのマッチングを完了します.これで辞書順が最小になります.
コード#コード#
#include
#include
#include
#include
#include
#include
#define inf 2147483647
using namespace std;
typedef long long ll;
const int maxn = 100005;
char s[maxn];
int l[maxn],r[maxn],local[maxn];
int main()
{
// freopen("1009.txt", "r", stdin); // ¶áèë¸ÕD′μÄÎļt
// freopen("1009zhz.out", "w", stdout); // êä3ö½«òaêä3öμÄêy¾Y
int T;
int cnt=1;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
int len = strlen(s);
// if(cnt==8708)
// puts(s);
int lena=0,lenb=0,star=0;
for(int i=0; i<len; i++)
{
if(s[i]=='(')
l[lena++]=i+1;
else if(s[i]==')')
r[lenb++]=i+1;
else
local[star++]=i+1;
}
l[lena]=0;
r[lenb]=0;
local[star]=0;
bool falg = true;
int beg=0;
bool next = true;
for(int i=0,j=0; i<lenb; i++)
{
if(l[j]<r[i]&&l[j]!=0)
j++;
else
{
if(star==beg)
falg = false;
for(int z=beg; z<star; z++)
{
if(local[z]<r[i])
{
s[local[z]-1] = '(';
beg++;
break;
}
else if(z+1==star)
falg = false;
}
}
if(j+1>lena)
{
next = false;
}
}
if(next)
for(int i=lena-1,j=lenb-1; i>=0; i--)
{
if(l[i]<r[j])
j--;
else
{
if(star==beg)
falg = false;
for(int z=star-1; z>=beg; z--)
{
if(local[z]>l[i])
{
s[local[z]-1] = ')';
star--;
break;
}
else if(z==beg)
falg = false;
}
}
}
if(falg)
{
for(int i=0; i<len; i++)
{
if(s[i]!='*')
printf("%c",s[i]);
}
puts("");
}
else
{
puts("No solution!");
}
}
return 0;
}