如你所見,b組題,除了NC亂入直奔T2搶了我一個首殺以外A層學過FFT的人都沒有參加。
競爭壓力很小,題又簡單,所以就造就了6個AK。
然而並不計入總分,我仍然穩在第二機房。
T1lyl16分鍾切掉我也是佩服,我沒看數據范圍打錯復雜度(多了個二分)23分鍾碼完,T30。
思路都不是很毒瘤,代碼也很好打,加起來都沒有2k。
47分鍾時干掉T3后我覺得差不多AK了,去廁所聽到隔壁聽講FFT的聲音,有些難過。
回來之后打開題庫翻看FFT的題目看了半個小時左右。
然后自覺無聊,重新算了一下T1復雜度發現會被卡,改了。
過了一會,教練叫我去隔壁聽了一會講。。。
因為T1的失手導致了少聽了33分鍾的課。。。吸取教訓
一定要認真算好復雜度再開始打。
T1:X國的軍隊
考慮貪心並逆推。把b數組都減去a數組的量表示戰后至少剩下多少人。
考慮每個任務放進優先隊列里,只要戰后剩余人數足夠就繼續,否則就補人。

1 #include<cstdio> 2 #include<queue> 3 using namespace std; 4 priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q; 5 int a[100005],b[100005]; 6 int read(){ 7 register int p=0;register char ch=getchar(); 8 while(ch>'9'||ch<'0')ch=getchar(); 9 while(ch<='9'&&ch>='0')p=(p<<3)+(p<<1)+ch-'0',ch=getchar(); 10 return p; 11 } 12 int main(){ 13 int t=read(); 14 while(t--){ 15 int n=read();long long tot=0,now=0,ex=0; 16 for(int i=1;i<=n;++i)a[i]=read(),b[i]=read(),tot+=a[i],q.push(make_pair(b[i]-a[i],i)); 17 while(!q.empty()){ 18 int x=q.top().first; 19 if(x>now)ex+=x-now,now=x; 20 now+=a[q.top().second],q.pop(); 21 } 22 printf("%lld\n",ex+tot); 23 } 24 }
T2:排列組合
考慮式子的實際含義,把每一項的第二個組合數改寫一下就是$\sum\limits_{i=0}^{n}C_n^i C_n^{n-i}$
那么就是在2n個物品里選n個的全部可能。
數組開2倍。肯定有人出鍋了。

1 #include<cstdio> 2 #define int long long 3 #define mod 1000000007 4 int fac[2000005],invv[2000005],inv[2000005]; 5 main(){ 6 int t,n;scanf("%lld",&t); 7 inv[0]=inv[1]=invv[1]=fac[0]=fac[1]=1; 8 for(int i=2;i<=2000000;++i)fac[i]=fac[i-1]*i%mod,invv[i]=mod-mod/i*invv[mod%i]%mod,inv[i]=inv[i-1]*invv[i]%mod*invv[i]%mod; 9 while(t--)scanf("%lld",&n),printf("%lld\n",fac[n<<1]*inv[n]%mod); 10 }
T3:回文
發現串長很小,准備亂搞。
可以S2處理所有回文串。暴力即可。記錄每一個回文串的兩端點。
每次詢問就是求有多少個回文串左端點比L大右端點比R小。
普通的二維偏序,值域只有5000*5000,樹狀數組解決。

1 #include<cstdio> 2 int l,t[5005][5005];char s[5005]; 3 void add(int x,int y){for(;x<=l;x+=x&-x)for(int j=y;j<=l;j+=j&-j)t[x][j]++;} 4 int ask(int x,int y,int a=0){for(;x;x-=x&-x)for(int j=y;j;j-=j&-j)a+=t[x][j];return a;} 5 int main(){ 6 scanf("%s",s+1);while(s[l+1])l++; 7 for(int i=1;i<=l;++i)for(int j=0;j<i&&i+j<=l;++j)if(s[i-j]==s[i+j])add(l+1-(i-j),i+j);else break; 8 for(int i=1;i<l;++i)for(int j=0;j<i&&i+j+1<=l;++j)if(s[i-j]==s[i+j+1])add(l+1-(i-j),i+j+1);else break; 9 int t,L,R;scanf("%d",&t);while(t--)scanf("%d%d",&L,&R),printf("%d\n",ask(l+1-L,R)); 10 }