1. 程式人生 > 實用技巧 >「聯賽模擬測試34」題解

「聯賽模擬測試34」題解

T1:666

發現長為 \(s\) 的串能從兩個地方轉移過來:

  • \(\frac{s}{2},\frac{s}{3},\frac{s}{4},...,\frac{s}{k}\)\(k|s\)),代價為 \(k\),即複製一次,貼上 \(k-1\)

  • \(s+1,s+2,...,s+k\) 代價為 \(k\) ,即按撤銷的次數

\(n^2\) 的DP就能寫了

考場第一類轉移代價寫錯了,外加時間卡成了 \(200ms\),得到了 \(14pts\)

第二類轉移發現 \(f_s\) 最多被 \(f_{s+2}\) 更新,證明不會

第一類轉移比較神奇,玄學做法是 \(f_s\) 只會被 \(f_{\frac{s}{2}}\)

\(f_{\frac{s}{3}}\) \(f_{\frac{s}{5}}\) \(f_{\frac{s}{7}}\) ,證明也不會

我的做法是後 \(2w\) 的數打表,能過

T2:春思

沙雕題

先考慮 \(a=c^k\)\(a\) 只有一個因數的情況

手模一下,發現是個等差數列:

\[ans=a\times \frac{a^b-1}{a-1} \]

再用暴力搞搞其他的,發現答案是所有質因子的\(ans\)相乘

時間複雜度: \(O(\sqrt{n})\)

注意底數為 \(1\) 的情況,即 質因子 \(c mod 9901 = 1\),特判一下

        ll ans=1;
	for(register int i=1;i<=tot;i++){
		if(a%prime[i]==0){
			ll cnt=1,sum=0;
			while(a%prime[i]==0)a/=prime[i],cnt*=prime[i],cnt%=mol,sum+=cnt;
			if(prime[i]%mol!=1)ans=ans*(sum%mol*(qpow(cnt,b)-1)%mol*qpow(cnt-1,mol-2)%mol+1)%mol;
			else ans=ans*((b+1)%mol)%mol;
			if(a==1)break;
		}
	}
	if((a-1)%mol!=0&&a!=1)ans=ans*(a%mol*(qpow(a%mol,b)-1)%mol*qpow(a-1,mol-2)%mol+1)%mol;
	else if(a!=1)ans=ans*(b+1)%mol;
	cout<<ans<<endl;

T3:密州盛宴

考場直接衝T4DP了,沒開正解

正解是個貪心

無解一定是 \(0\) 的個數大於 \(1\) 的個數,否則一定有解

計字尾中 \(0\)\(1\) 的差的最大值為 \(maxsum\),答案一定是 \(max(maxsum-1,0)\)

從後往前掃,如果0的個數大於1的個數,直接把0提至最前,對答案貢獻 \(+1\)

後三十分隨便搞搞就行了

while(1){
		n=read(),m=read();
		ans=-INF;
		if(!n&&!m)break;
		cnt0=cnt1=0;
		for(int i=1,x;i<=m;i++){
			cin>>s[i];
			scanf("%lld",&a[i]);
		}
		for(int i=m;i>=1;i--){
			len=s[i].size();
			int cnt00=0,cnt11=0,Max=-INF;
			for(int j=len-1;j>=0;j--){
				if(s[i][j]=='0')cnt00++;
				else cnt11++;
				Max=max(cnt00-cnt11,Max);
			//	cout<<s[i][j]<<" asd  "<<cnt00<<" "<<cnt11<<endl;
			}
			if(cnt00-cnt11<0)ans=max(ans,cnt0-cnt1+Max);
			else ans=max(ans,cnt0-cnt1+(a[i]-1)*(cnt00-cnt11)+Max);
			cnt0+=cnt00*a[i];
			cnt1+=cnt11*a[i];
			//cout<<i<<" "<<cnt0<<" "<<cnt1<<endl;
		}
		if(cnt1<n)puts("-1");
		else printf("%lld\n",max(ans-1,0LL));
	}

T4:赤壁情

\(60pts\)隨機化:

while(clock()/CLOCKS_PER_SEC<3.0){
				random_shuffle(a+1,a+1+n);
				sum=0;maxsum++;
				for(int i=1;i<n;i++)sum+=abs(a[i]-a[i+1]);
				if(sum>=m)ans++;
			}
			cnt=maxsum;

正解記搜優化DP,沽了