有些东西渐渐就远去了。。。不必挂念。
只有时间才拥有如此力量。我们能做的,唯有释怀。
这次的题格外顺手,大概是我的强项了。
但是考得还是不够好吧。。。感觉可以更高的
今天迎来了学了OI一年多比较重要的一个成就:(虽说是在考后)
$AC1000$道题!还是挺不容易的。
第$1000$道题是今天的T3。大部分是自己思考的,题也不是很简单,挺好的。
挺过了联赛,现在想要等到下一次整百,可能就要到3月份了。
我还能在OI多久呢?
回到这场考试。
T1的数据范围只有$10000$,让我想起了$ALO$那道题$50000$数据被我随机化$AC$。
然而这题可以构造毒瘤数据所以正确率没有那么高,但是除了随机化啥也不会写。
于是拿一个$60$走人(其实很满意了)。
T2一眼秒,$AC$自动机+拓扑$dp$,当然需要$tarjan$。
$tarjan$?啊。。。好像不会写了,弃了。
然后正解真的就是这个,自闭。。。
T3其实是最先开始做的题,因为测试1里做的那道题有提到积性函数,然后就想了一下这题的这玩意显然也就是积性函数。
然后$P=2$的就很好说了。很快写完。然后又研究了一下$P=2017$,也就证明了结论但是复杂度不对,一共$80$分滚粗。
这点分拿到之后就啥都没干了。T2写了个$AC$自动机但是没有$tarjan$没有用。然后就不知道该干什么了。
$tarjan$这种东西吧。。。
至少现在,应该是真的会了。。。幸亏联赛没考不然就退役了。
T1:好题
题意:树上每个点有色,求最小联通块含有k种颜色。$ n \le 10000,k \le 5$,颜色$\le$n
$k \le 5$一定是突破口。但是颜色那么多怎么办?
随机化。把所有的颜色分成k类,同类的视为一种颜色。
然后树上状压$dp$就可以得到含有k类颜色的最小联通块。
显然找到的方案一定是合法的,但不一定是最优的。
考虑最优方案的联通块所包含的$k$种颜色,你能找出这个解当且仅当这k种颜色被恰好分为了不同的$k$类。
合法的总方案是$k!$个(内部顺序任意,所以是排列)。而对这k中颜色分类的总方案数就是$k^k$。
所以单次随机化得到正解的概率是$\frac{k!}{k^k}$。在$k=5$时大约是$4 \%$
这样的话,只要进行$50$次随机化,正确率就已经高达$87 \% $了。然而你让它一直$clock$跑下去肯定是不会错的。
单次随机化的复杂度是$O(3^kn)$。然而我懒得写枚举子集了,于是单次复杂度变为$O(4^kn)$。
还是可以过的。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define S 10003 4 int n,k,fir[S],l[S<<1],to[S<<1],co[S],ec,cnt,c,ans=S,tans,sz[S],dp[S][33],re[S],Co[S]; 5 void dfs(int p,int fa){ 6 dp[p][1<<co[p]]=1; 7 for(int i=fir[p];i;i=l[i])if(to[i]!=fa){ 8 dfs(to[i],p); 9 for(int a=1;a<1<<k;++a)for(int b=1;b<1<<k;++b)dp[p][a|b]=min(dp[p][a|b],dp[p][a]+dp[to[i]][b]); 10 }ans=min(ans,dp[p][(1<<k)-1]); 11 } 12 main(){ 13 scanf("%d%d",&n,&k); 14 for(int i=1;i<=n;++i)scanf("%d",&Co[i]); 15 for(int i=1,x,y;i<n;++i)scanf("%d%d",&x,&y), 16 l[++ec]=fir[x],fir[x]=ec,to[ec]=y, 17 l[++ec]=fir[y],fir[y]=ec,to[ec]=x; 18 while(clock()<699999){ 19 for(int i=1;i<=n;++i)re[i]=rand()%k; 20 for(int i=1;i<=n;++i)co[i]=re[Co[i]]; 21 memset(dp,0x3f,sizeof dp);dfs(1,0); 22 }printf("%d\n",ans); 23 }