這次的題挺奇怪的。
大概是比較簡單。。。也許吧?
$T1$暴力顯然可過,就沒什么可說的。
$T2$題目或者$std$鍋了,好氣啊本來能搶到兩個綠框的。
不到三小時的時候先$AC$了一遍,結果發現自己的邊界是錯的(然而$std$也是錯的)。
所以改成對的,然后就和$std$不一樣了,然后就$WA$了。
$T3$一眼看着像$min25$篩然后就自閉了,嘗試寫然而並沒有寫出來。暴力跑路。
雖說$min25$的確應該可以過,但是正解簡單得多,想復雜了。。。
T1:決戰
大意:$n \times 3$的矩陣,每個棋子周圍$8$個格子中的一些不能放置其它棋子。求放置$m$棋子的方案數。$n \le 2500$
直接暴力$dp$。$O(n^2)$顯然可過啊。

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 998244353 4 #define ri register int 5 void add(int&a,int b){a+=b;if(a>=mod)a-=mod;} 6 int dp[2][7501][8],ok[8],tr[8][8],n,m,ban[3][3],t[8][9]; 7 const int bit[]={0,1,1,2,1,2,2,3}; 8 int main(){ 9 ri n,m,ans=0; cin>>n>>m; 10 for(int i=0;i<3;++i)for(int j=0;j<3;++j)cin>>ban[i][j]; 11 if(ban[0][0]||ban[2][2])for(int i=0;i<8;++i)for(int j=0;j<8;++j)if(i>>1&j)tr[i][j]=1; 12 if(ban[0][2]||ban[2][0])for(int i=0;i<8;++i)for(int j=0;j<8;++j)if(j>>1&i)tr[i][j]=1; 13 if(ban[0][1]||ban[2][1])for(int i=0;i<8;++i)for(int j=0;j<8;++j)if(j&i)tr[i][j]=1; 14 if(ban[1][0]||ban[1][2])for(int i=0;i<8;++i)for(int j=0;j<8;++j)if(j>>1&j||i>>1&i)tr[i][j]=1; 15 for(int i=0;i<8;++i)for(int j=0;j<8;++j)if(!tr[i][j])t[i][++t[i][0]]=j; 16 dp[0][0][0]=1; ri mx=0,nw=1,nx=0,_=0,C=m-3*n-3; 17 while(nw^=1,nx^=1,C+=3,_++<n)for(ri i=0;i<8;++i)if(t[i][0])for(ri j=max(C,0);j<=m&&j<=_+_+_;++j)if(dp[nw][j][i]){ 18 for(ri k=t[i][0],g;g=t[i][k],k;--k)add(dp[nx][j+bit[g]][g],dp[nw][j][i]); 19 dp[nw][j][i]=0; 20 }for(ri i=0;i<8;++i)add(ans,dp[nw][m][i]); cout<<ans<<endl; 21 }
T2:gift
大意:$n$點,選有$A_i$代價,$x_i,y_i$同時選有$B_i$貢獻。最大化$\lfloor \frac{\sum B -1}{\sum A} \rfloor$。$n \le 400,m\le 10^5$
$01$分數規划+網絡流。用那種$n$點$2m$邊的寫法。但是好像$n+m$點也能過。
千萬不要處理$B$整除$A$的情況,不然會$WA$

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define S 2222222 5 #define s 4005 6 int n,m,c[s],e[s][s],w[S],fir[s],l[S],to[S],v[S],ec=1,tw[s],tot,d[s],q[s]; 7 bool bfs(){ 8 for(int i=1;i<=n+1;++i)d[i]=0; d[0]=1; 9 for(int h=1,t=1;h<=t;++h)for(int i=fir[q[h]];i;i=l[i])if(v[i]&&!d[to[i]]) 10 d[q[++t]=to[i]]=d[q[h]]+1; 11 return d[n+1]; 12 } 13 int dfs(int p,int f){ 14 if(p==n+1)return f; int r=f; 15 for(int i=fir[p];i&&r;i=l[i])if(d[to[i]]==d[p]+1&&v[i]){ 16 int x=dfs(to[i],min(v[i],r)); 17 if(!x)d[to[i]]=0; 18 v[i]-=x; v[i^1]+=x; r-=x; 19 }return f-r; 20 } 21 void link(int a,int b,int W){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;w[ec]=W;} 22 void con(int a,int b,int W){link(a,b,W);link(b,a,W);} 23 int main(){//freopen("0.in","r",stdin); 24 cin>>n>>m; 25 for(int i=1;i<=n;++i)scanf("%d",&c[i]),c[i]<<=1,con(0,i,0); 26 for(int i=1,x,y,W;i<=m;++i)scanf("%d%d%d",&x,&y,&W),e[x][y]+=W,e[y][x]+=W,tw[x]+=W,tw[y]+=W,tot+=W+W; 27 for(int i=1;i<=n;++i)for(int j=i+1;j<=n;++j)if(e[i][j])con(i,j,e[i][j]); 28 for(int i=1;i<=n;++i)tot-=e[i][i],tw[i]-=e[i][i]; 29 for(int i=1;i<=n;++i)link(i,n+1,tw[i]),link(n+1,i,0); 30 int l=0,r=700,md,Ans; 31 while(md=l+r>>1,l<=r){ 32 for(int i=2;i<=ec;++i)v[i]=w[i]; 33 ll ans=tot; 34 for(int i=1;i<=n;++i)if(md*c[i]-e[i][i]>=0)v[i<<1]=md*c[i]-e[i][i];else ans+=e[i][i]-md*c[i]; 35 while(bfs())ans-=dfs(0,0x7fffffff); 36 if(ans<=0)r=md-1;else l=Ans=md,l++; 37 }cout<<Ans<<endl; 38 }
T3:質數
大意:求$\sum\limits_{i=1}^{n} 2^{f(i)}$。$f(i)$表示$i$的質因子種數。$ n\le 10^{12} $
含義理解,$2^{f(i)}$可以理解為把所有質因子分成兩個集合,同一種的所有次數出現在同一個集合中。
$2^{f(i)} = \sum\limits_{j|i}[gcd(j,\frac{i}{j})=1] = \sum\limits_{j|i} \sum\limits_{p|j,p|\frac{i}{j}} \mu(p)=\sum\limits_{p=1} \mu(p) \sum\limits_{p^2|i}^{i \le n} d(\frac{i}{p^2}) $
$ans=\sum\limits_{p=1}^{ \sqrt{n} } \mu(p) \sum\limits_{i=1}^{\frac{n}{p^2}} d(i)$
其中$\sum\limits_{i=1}^{n} d(i) = \sum\limits_{i=1}^{n} \frac{n}{i}$
得到$ans=\sum\limits_{p=1}^{\sqrt{n}} \mu(p) \sum\limits_{i=1}^{\frac{n}{p^2}} \frac{n}{ip^2}$
整除分塊。

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 998244353 4 #define S 2333333 5 #define ll long long 6 ll n;int ans,p[S],pc,np[S],mu[S]; 7 ll cal(ll n,int a=0){for(ll i=1,l,N;N=n/i,i<=n;i=l+1)l=n/N,a=(a+1ll*(l-i+1)*N)%mod;return a;} 8 int main(){ 9 cin>>n; int sq=sqrt(n); mu[1]=1; 10 for(int i=2;i<=sq;++i){ 11 if(!np[i])p[++pc]=i,mu[i]=-1;; 12 for(int j=1;i*p[j]<=sq;++j) 13 if(i%p[j])np[i*p[j]]=1,mu[i*p[j]]=-mu[i]; 14 else {np[i*p[j]]=1;break;} 15 } 16 for(int p=1;p<=sq;++p)ans=(ans+cal(n/p/p)*mu[p])%mod; 17 cout<<(ans+mod)%mod; 18 }