1. 程式人生 > >2018.12.08【NOIP提高組】模擬B組

2018.12.08【NOIP提高組】模擬B組

遲到的解題報告

JZOJ 5123 diyiti

bzoj 4927 連結

分析

6根木棍,只能是3+1+1+1或者是2+2+1+1,所以分類討論。(以下其它情況都排除了之前的情況,也就是容斥

,為了行文方便,在此不多寫)
設邊長為 x x i × 2 i\times2 代表 i
i i和i

2+2+1+1的組合方式
x , x
, x 2 × 2 , x 2 × 2 ( x ) x,x,\frac{x}{2}\times 2,\frac{x}{2}\times 2(x是偶數)
以下保證 t × 2 < x t\times2<x
x , x , x t t , x t t x,x,x-t和t,x-t和t
x , x , x t 1 t 1 , x t 2 t 2 t 1 t 2 x,x,x-t_1和t_1,x-t_2和t_2(t_1\neq t_2)
x , x , x t t , x 2 × 2 ( x ) x,x,x-t和t,\frac{x}{2}\times 2(x是偶數)
3+1+1+1的組合方式
x , x , x , x 3 × 3 ( x 3 ) x,x,x,\frac{x}{3}\times3(x能被3整除)
x , x , x , x t 1 × 2 t 1 t 1 x,x,x,x-t_1\times 2和t_1和t_1
x , x , x , x t 1 t 2 t 1 t 2 ( x t 1 t 2 t 1 t 2 ) x,x,x,x-t_1-t_2和t_1和t_2(x-t_1-t_2\neq t_1\neq t_2)

這樣講好像很簡單,實際上實踐會比較容易在細節上出問題,我的細節出錯點詳見程式碼


程式碼

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <vector>
#define rr register
using namespace std;
const int N=10000001;
typedef long long ll; ll ans;
vector<int>t; int cnt[N+10],dcnt[N+10];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
signed main(){
	freopen("yist.in","r",stdin);
	freopen("yist.out","w",stdout);
	for (rr int n=iut(),x;n;--n)
	    if (++cnt[x=iut()]==1) t.push_back(x);
	sort(t.begin(),t.end());
	for (rr int i=0;i<t.size()-1;++i)
	    for (rr int j=i+1;j<t.size();++j)
	        if (t[i]+t[j]<N)
			    dcnt[t[i]+t[j]]+=cnt[t[i]]*cnt[t[j]];//原始碼只是=
			else break;
	for (rr int i=1;i<t.size();++i){
		if (cnt[t[i]]==1) continue;
		if (cnt[t[i]]>1){
			rr ll x=1ll*cnt[t[i]]*(cnt[t[i]]-1)>>1,sum=0;
			if (!(t[i]&1)&&cnt[t[i]>>1]>3)
			    ans+=x*cnt[t[i]>>1]*(cnt[t[i]>>1]-1)*(cnt[t[i]>>1]-2)*(cnt[t[i]>>1]-3)/3>>3;//原始碼判成奇數
			for (rr int j=0;j<i;++j)
			if ((t[j]<<1)<t[i]){
				if (cnt[t[j]]>1&&cnt[t[i]-t[j]]>1)
				    sum+=1ll*cnt[t[j]]*(cnt[t[j]]-1)*cnt[t[i]-t[j]]*(cnt[t[i]-t[j]]-1)>>2;
			}else break;
			ans+=x*sum; sum=0;
			for (rr int j=0;j<i;++j)
			if ((t[j]<<1)<t[i]){
			    if (cnt[t[i]-t[j]])
			        ans+=x*sum*cnt[t[j]]*cnt[t[i]-t[j]],sum+=cnt[t[j]]*cnt[t[i]-t[j]];
			}else break;
			if (!(t[i]&1)) ans+=x*sum*cnt[t[i]>>1]*(cnt[t[i]>>1]-1)>>1;//原始碼未判斷
		}
		if (cnt[t[i]]==2