1. 程式人生 > >2018SD省隊集訓R1 D3

2018SD省隊集訓R1 D3

T1

題解:

首先你可以寫一個n=L的暴力,這樣可以得到20pts
Polya定理的應用。先來看Polya定理。

Polya定理:設 G = {a1,a2,…,ag}是 N 個物件的置換群,用 M 種顏色給這 N 個物件著色,則不同的著色 方案數為:|G|^(-1) * {M^c(a1) + M^c(a2) + … + M^c(ag)}。

其中 c(ai)為置換 ai 的迴圈節數,( i = 1,2,…,g )。

對於這道題,直接用Polya定理求解,找出所有的置換,並求出置換的迴圈節數。然後根據上邊公式求出 M^c(ai) 的總和,再除以置換群個數。

對於這個題目,用的是旋轉置換,分別順時針旋轉 i 個珠子,其迴圈節長度為 LCM(N,i) / i,迴圈節數為N / (LCM(N,i) / i),即 GCD(N,i)。

程式碼:

20pts

#include <cstdio>
#include <iostream>
#define LL long long 
using namespace std;
const int mod=1e9+7;
const int N=1000005;
LL mul[N],inv[N];
LL ksm(LL a,LL k)
{
    LL ans=1;
    for (;k;k>>=1,a=a*a%mod)
      if (k&1) ans=ans*a%mod;
    return ans;
}
int gcd(int a,int
b){if (!b) return a;else return gcd(b,a%b);} int main() { freopen("color.in","r",stdin); freopen("color.out","w",stdout); int n,k,l;scanf("%d%d%d",&n,&k,&l); if (n==l) { LL sum=0; for (int i=1;i<=n;i++) sum=(sum+ksm(k,gcd(n,i)))%mod; sum=sum*ksm
(n,mod-2)%mod; printf("%lld",sum); } }

T2

題解:

挖坑待填

程式碼:

T3

題解:

這個題目考場上一眼暴力都不會寫。。。那就從暴力說起吧
我們可以列舉每一個格子的上三角形先被消掉還是下面的三角形先被消掉,我們假設上面的三角先被刪掉,可以建立一個依賴關係,像這樣
這裡寫圖片描述
然後可以瞎搞計數,這樣的複雜度是O((rc)2)=O(r4)

然後我們看看資料範圍發現O(r3)就能過了,優化並不是很多。

這裡寫圖片描述
(畫紅點的是開始走的點)
如果格子上面的三角形要被刪,那麼肯定要先刪格子[i-1][j],從上面開始,記憶化搜尋,O(r2c)

程式碼:

#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#define rep(i,n) for (int i = 0; i < n; ++i)
using namespace std;
typedef vector<int> VI;
typedef vector<VI > VVI;

const int INF = 1001001001;
const int di[] = {-1,0,1,0}, dj[] = {0,-1,0,1}; //^<v>

int h, w;
VVI used, dv;
int dfs(int i, int j, int v) {
  if (used[i][j] == 1) return INF;
  if (used[i][j] == 2) return 0;
  int res = 2;
  used[i][j] = 1;
  rep(k,2) {
    int nv = v^(dv[i][j]*k);
    int ni = i + di[nv], nj = j + dj[nv];
    if (ni < 0 || nj < 0 || ni >= h || nj >= w) continue;
    int r = dfs(ni,nj,nv);
    if (r == INF) return INF;
    res += r;
  }
  used[i][j] = 2;
  return res;
}

int main() {
    freopen("grid.in","r",stdin);
    freopen("grid.out","w",stdout);
  cin >> h >> w;
  vector<string> s(h);
  rep(i,h) cin >> s[i];
  dv = VVI(h, VI(w));
  rep(i,h)rep(j,w) dv[i][j] = (s[i][j] == 'Z') ? 1 : 3;
  VVI ans(h, VI(w, INF));
  rep(j,w)for (int v = 0; v <= 2; v += 2) {
    used = VVI(h, VI(w));
    int sum = 0;
    rep(i,h) {
      int si = i;
      if (v == 2) si = h-1-i;
      int res = dfs(si,j,v);
      if (res == INF) break;
      sum += res;
      ans[si][j] = min(ans[si][j], sum);
    }
  }
  rep(i,h)rep(j,w) if (ans[i][j] == INF) ans[i][j] = -1;
  rep(i,h)rep(j,w) printf("%d%c", ans[i][j], (j == w-1) ? '\n' : ' ');
  return 0;
}