A. Apple
按題意模擬即可。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 105, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n, m;
vector<int>a[N];
int ind1 = 0, ind1num = 0;
int ind2num = 0;
int ind3 = 0, ind3num = 0;
bool vis[N];
int ind[N];
int cnt;
bool dfs1(int x, int fa)
{
++cnt;
vis[x] = 1;
for(auto y : a[x])if(y != fa)
{
if(!vis[y])
{
if(!dfs1(y, x))return 0;
}
else if(y != ind3)return 0;
}
return 1;
}
void dfs3(int x, int fa)
{
++cnt;
vis[x] = 1;
for(auto y : a[x])if(y != fa)
{
if(!vis[y])
{
dfs3(y, x);
}
}
}
bool solve()
{
if(ind1num != 1)return 0;
if(ind2num != n - 2)return 0;
if(ind3num != 1)return 0;
cnt = 0;
vis[ind3] = true;
if(!dfs1(ind1, 0))return 0;
dfs3(ind3, 0);
if(cnt != n)return 0;
return 1;
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
while(~scanf("%d%d", &n, &m))
{
for(int i = 1; i <= n; ++i)
{
a[i].clear();
ind[i] = 0;
vis[i] = 0;
}
for(int i = 1; i <= m; ++i)
{
int x, y; scanf("%d%d", &x, &y);
a[x].push_back(y);
a[y].push_back(x);
++ind[x];
++ind[y];
}
ind1 = 0, ind1num = 0;
ind2num = 0;
ind3 = 0, ind3num = 0;
for(int i = 1; i <= n; ++i)
{
if(ind[i] == 1)
{
++ind1num;
ind1 = i;
}
else if(ind[i] == 2)
{
++ind2num;
}
else if(ind[i] == 3)
{
++ind3num;
ind3 = i;
}
}
puts(solve() ? "Yes" : "No");
}
return 0;
}
/*
【trick&&吐槽】
【題意】
【分析】
【時間複雜度&&優化】
9 9
1 2
2 3
3 5
5 6
6 4
4 7
1 7
7 9
8 9
5 5
1 2
2 3
1 3
1 4
1 5
4 4
1 2
2 3
1 3
1 4
5 4
1 2
2 3
1 3
1 4
*/
B. Bar charts
關於序列的字首和建立差分約束系統,SPFA判斷是否存在負環。
#include<cstdio>
#include<cstdlib>
using namespace std;
const int N=12222,M=1000000,E=10000000,inf=~0U>>1;
int n,i,g[N],v[M],w[M],nxt[M],ed,d[N];
int x,h,t,q[E];
int vis[N],in[N];
inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
inline void make(int x,int y,int z){
//x-y=z
add(y,x,z);
add(x,y,-z);
}
void gao(){
int k,b,s;
scanf("%d%d%d",&k,&b,&s);
make(b-1,0,0);
for(int i=b+k*s;i<=n;i++)make(i,i-1,0);
for(int i=1;i<=k;i++){
int l=b+(i-1)*s,r=b+i*s;
int o;
scanf("%d",&o);
//s[r-1]-s[l-1]
make(r-1,l-1,o);
}
}
void NO(){
puts("No");
exit(0);
}
inline void ext(int x,int y){
if(y<0)NO();
if(y>=d[x])return;
d[x]=y;
if(!in[x]){
in[x]=1;
vis[x]++;
if(vis[x]>=n)NO();
q[++t]=x;
if(t>=E-10)NO();
}
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=11111;
for(i=0;i<n;i++)add(i+1,i,0);
gao();
gao();
for(i=0;i<=n;i++){
d[i]=inf;
}
h=1,t=0;
ext(0,0);
while(h<=t){
x=q[h++];
for(i=g[x];i;i=nxt[i])ext(v[i],d[x]+w[i]);
in[x]=0;
}
puts("Yes");
}
C. Construction sets
二分答案,二進位制拆分揹包+bitset檢驗。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 55, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n, mn, mx;
int m[N], c[N];
bitset<10005>f;
bool check(int K)
{
f.reset(); f[0] = 1;
for(int i = 1; i <= n; ++i)
{
int tot = c[i] / K;
int g = 1;
LL v = m[i];
while(tot)
{
if(v > mx)break;
f |= f << v;
tot -= g;
g = min(g * 2, tot);
v = (LL)m[i] * g;
}
}
for(int j = mn; j <= mx; ++j)
{
if(f[j])return 1;
}
return 0;
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
while(~scanf("%d%d%d", &n, &mn, &mx))
{
for(int i = 1; i <= n; ++i)
{
scanf("%d%d", &m[i], &c[i]);
}
int l = 0;
int r = 1e6;
while(l < r)
{
int mid = (l + r + 1) >> 1;
if(check(mid))
{
l = mid;
}
else
{
r = mid - 1;
}
}
printf("%d\n", l);
}
return 0;
}
/*
【trick&&吐槽】
【題意】
【分析】
【時間複雜度&&優化】
3 12 13
3 8
4 6
7 9
*/
D. Dinner party
$f[i][j]$表示面積和為$i$的矩形,周長和為$j$是否有可能,bitset加速。
#include<cstdio>
#include<bitset>
using namespace std;
const int N=1010,M=2010;
int T,n,m,i,j,x,y,cnt;
bitset<M>f[N];
void solve(){
scanf("%d%d",&n,&m);
if(m%2){
puts("No");
return;
}
m/=2;
if(f[n][m]==0){
puts("No");
return;
}
puts("Yes");
int cnt=0;
static int q[100000][2];
while(n){
int X=0,Y=0;
for(x=1;x<=n;x++){
for(y=1;y*x<=n;y++)if(x+y<=m)if(f[n-x*y][m-x-y]){
X=x,Y=y;
break;
}
if(X)break;
}
q[++cnt][0]=X;
q[cnt][1]=Y;
n-=X*Y;
m-=X+Y;
}
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)printf("%d %d\n",q[i][0],q[i][1]);
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
//scanf("%d%d",&n,&m);
n=1000;
m=2000;
f[0][0]=1;
for(i=0;i<=n;i++)
for(x=1;x+i<=n;x++)
for(y=1;x*y+i<=n;y++)
f[i+x*y]|=f[i]<<(x+y);
scanf("%d",&T);
while(T--)solve();
}
E. Expression on dice
若要構造$=$,則在兩側構造$0$即可,否則隨意構造。
//
// main.cpp
// opencup 10378 E
//
// Created by luras on 2017/9/14.
// Copyright © 2017年 luras. All rights reserved.
//
#define ms(x, y) memset(x, y, sizeof(x))
#define mc(x, y) memcpy(x, y, sizeof(x))
#define lson o << 1, l, mid
#define rson o << 1 | 1, mid + 1, r
#define ls o << 1
#define rs o << 1 | 1
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<map>
#include<stack>
#include<time.h>
#include<vector>
#include<list>
#include<set>
#include<iostream>
#include<stdlib.h>
#include<string>
#include<algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
template <class T> inline void gmax(T &a, T b){if(b > a) a = b;}
template <class T> inline void gmin(T &a, T b){if(b < a) a = b;}
using namespace std;
const int N = 1e6 + 10, M = 2e6 + 10, Z = 1e9 + 7, maxint = 2147483647, ms1 = 16843009, ms31 = 522133279, ms63 = 1061109567, ms127 = 2139062143;
const double PI = acos(-1.0), eps = 1e-8;
typedef long long LL;
void fre()
{
freopen("/Users/luras/Desktop/in.txt", "r", stdin);
freopen("/Users/luras/Desktop/out.txt", "w", stdout);
}
const int INF = 1e9;
int casenum, casei;
int priv[N];
double calc(double a, double b, char op)
{
if(op == '+') return a + b;
if(op == '-') return a - b;
if(op == '*') return a * b;
if(op == '/') return a / b;
return 0;
}
double calculate(string str)
{
stack<double> num;
stack<char> oper;
priv['+'] = priv['-'] = 3;
priv['*'] = priv['/'] = 2;
priv['('] = 10;
double x, y, t = 0;
int i; char last = 0;
for(i = 0; i < str.length(); i ++){
if(isdigit(str[i])){
num.push(atof(str.c_str() + i));
for(; i + 1 < str.length() && isdigit(str[i + 1]); i ++);
if(i + 1 < str.length() && str[i + 1] == '.')
for(i ++; i + 1 < str.length() && isdigit(str[i + 1]); i ++);
}
else if(str[i] == '('){
oper.push(str[i]);
}
else if(str[i] == ')'){
while(oper.top() != '('){
y = num.top(); num.pop();
x = num.top(); num.pop();
char op = oper.top();
oper.pop();
num.push(calc(x, y, op));
}
oper.pop();
}
else if(str[i] == '-' && (last == 0 || last == '(')){
num.push(0.0);
oper.push('-');
}
else if(priv[str[i]] > 0){
while(oper.size() > 0 && priv[str[i]] >= priv[oper.top()]){
y = num.top(); num.pop();
x = num.top(); num.pop();
char op = oper.top();
oper.pop();
num.push(calc(x, y, op));
}
oper.push(str[i]);
}else continue;
last = str[i];
}
while(oper.size() > 0){
y = num.top(); num.pop();
x = num.top(); num.pop();
char op = oper.top();
oper.pop();
num.push(calc(x, y, op));
}
return num.top();
}
map<int, bool> mop;
vector<int> num;
vector<char> sym;
int lft, rgt, zero, divi, typ;
const string sta[6][6] ={
{"=", "<", ">", "!=", "<=", ">="},
{"4", "+", "-", "(", "(", ")"},
{"0", "/", "/", "/", "8", "+"},
{"2", "3", "4", "5", "-", ")"},
{"+", "-", "*", "/", "1", "9"},
{"6", "7", "+", "-", "(", ")"}
};
void ask(int o)
{
char ch;
if(o == 2){
puts("2");
fflush(stdout);
scanf(" %c", &ch);
//ch = sta[1][rand() % 6][0];
//cout << "A: " << ch;
if(ch == '(') lft ++;
else if(ch == ')') rgt ++;
else if(ch == '4') {
num.push_back(ch);
if(mop[ch] == 0){
mop[ch] = 1;
typ ++;
}
}
else sym.push_back(ch);
}
else if(o == 3){
puts("3");
fflush(stdout);
scanf(" %c", &ch);
//ch = sta[2][rand() % 6][0];
//cout << "A: " << ch;
if(ch == '0') zero ++;
else if(ch == '8') {
num.push_back(ch);
if(mop[ch] == 0){
mop[ch] = 1;
typ ++;
}
}
else if(ch == '/') divi ++;
else sym.push_back(ch);
}
else if(o == 4){
puts("4");
fflush(stdout);
//ch = sta[3][rand() % 6][0];
//cout << "A: " << ch;
scanf(" %c", &ch);
if(ch == '-') sym.push_back(ch);
else if(ch == ')') rgt ++;
else {
num.push_back(ch);
if(mop[ch] == 0){
mop[ch] = 1;
typ ++;
}
}
}
}
string ans;
string s;
string ss;
int sgn(double x)
{
if(fabs(x) < eps) return 0;
return x > 0 ? 1 : -1;
}
bool choose()
{
s = "";
int DIV = divi, ZERO = zero;
int n = num.size(), m = sym.size() + DIV;
int bas = (n + ZERO) / (m + 1);
int mo = (n + ZERO) - (m + 1) * bas;
int t = 0, j = -1, k = -1;
for(int i = 0; i < m + 1; i ++){
if(mo){
if(j + 1 >= n) return 0; // 必須得放前導0了
s += num[++ j]; ++ t;
while(t <= bas && ZERO){
s += '0'; t ++; ZERO --;
}
while(t <= bas){
s += num[++ j]; t ++;
}
mo --;
t = 0;
}
else{
if(j + 1 >= n) return 0;
s += num[++ j]; ++ t;
while(t < bas && ZERO){
s += '0'; t ++; ZERO --;
}
while(t < bas){
s += num[++ j]; t ++;
}
t = 0;
}
if(DIV){
s += '/';
DIV --;
}
else{
if(k + 1 < sym.size())s += sym[++ k];
}
}
return 1;
}
bool check(int o)
{
if(o == 0){
zero -= 2; lft --; rgt --; divi --;
if(!choose()) {zero += 2; lft ++; rgt ++; divi ++; return 0;}
if(calculate(s) != 0){
ans = "";
for(int i = 0; i < lft; i ++) ans += '(';
ans += '0';
for(int i = 0; i < rgt; i ++) ans += ')';
ans += "=0/(" + s + ')';
}
else {zero += 2; lft ++; rgt ++; divi ++; return 0;}
}
else{
zero --;
if(!choose()) {zero ++;return 0;}
double tmp = calculate(s);
if(sgn(tmp) != 0){
if(ss[0] == '<' && sgn(tmp) > 0 || ss[0] == '>' && sgn(tmp) < 0){
ans = "";
for(int i = 0; i < lft; i ++) ans += '(';
ans += '0';
for(int i = 0; i < lft; i ++) ans += ')';
ans += ss + s;
}
else{
ans = "";
for(int i = 0; i < lft; i ++) ans += '(';
ans += s;
for(int i = 0; i < lft; i ++) ans += ')';
ans += ss + '0';
}
}
else if(ss == "!="){
ans = "";
for(int i = 0; i < lft; i ++) ans += '(';
ans += '0';
for(int i = 0; i < lft; i ++) ans += ')';
ans += ss + s;
}
else {zero ++; return 0;}
}
return 1;
}
int main()
{
srand(time(NULL));
//fre();
puts("1");
fflush(stdout);
cin >> ss;
//ss = sta[0][rand() % 6];
//cout << ss << endl;
lft = rgt = zero = divi = typ = 0;
int tim = 0;
while(1){
if(++ tim == 1000){
int go = 1;
}
if(zero < (ss[0] == '=' ? 2 : 1) || divi == 0){
ask(3);
}
else if(lft < rgt || lft == 0){
ask(2);
}
else if(num.size() - 2 < sym.size() || rgt < lft){
ask(4);
}
else {
if(check(ss[0] == '=' ? 0 : 1)) break;
ask(4);
}
}
printf("0 ");
cout << ans << endl;
fflush(stdout);
return 0;
}
/*
題意:
型別:
分析:
優化:
trick:
資料:
Sample Input
Sample Output
>=
+ / / + 8 0 ) ( ) ( - - 5 5 5 - 4 4 4 - 5 3
*/
F. Flight trip
留坑。
G. Glasses with solutions
找出的子集需要滿足$b\sum m-a\sum t=0$,折半搜尋即可。
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
const int N=40;
int n,m,A,B,i,x,y,a[N];map<ll,ll>f;
ll ans;
void dfsl(int x,ll y){
if(x==m){f[y]++;return;}
dfsl(x+1,y+a[x]);
dfsl(x+1,y);
}
void dfsr(int x,ll y){
if(x==n){ans+=f[-y];return;}
dfsr(x+1,y+a[x]);
dfsr(x+1,y);
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d%d%d",&n,&A,&B);
for(i=0;i<n;i++){
scanf("%d%d",&x,&y);
a[i]=x*B-A*y;
}
m=n/2;
dfsl(0,0);
dfsr(m,0);
ans--;
printf("%lld",ans);
}
H. Hamburgers
對於每個漢堡,$O(2^6)$列舉所有它可以滿足的口味,然後對於每個人判斷是否滿足即可。
時間複雜度$O(m\sum a+2^6\sum b)$。
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N=55555;
int n,m,i,j,k,x,ans[N],mx[N],b[N];
vector<int>a[N];
bool v[(1<<26)+5];
inline int get(){
static char s[1000];
scanf("%s",s);
int t=0,len=strlen(s);
for(int i=0;i<len;i++)t|=1<<(s[i]-'a');
return t;
}
inline void make(int x,int y){
for(int i=x;i;i=(i-1)&x)v[i]=y;
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&k);
while(k--){
x=get();
a[i].push_back(x);
}
ans[i]=1;
}
scanf("%d",&m);
for(i=1;i<=m;i++){
scanf("%d",&k);
for(j=1;j<=k;j++)b[j]=get();
for(j=1;j<=k;j++)make(b[j],1);
for(j=1;j<=n;j++){
int t=0;
for(x=0;x<a[j].size();x++)if(v[a[j][x]])t++;
if(t>mx[j])mx[j]=t,ans[j]=i;
}
for(j=1;j<=k;j++)make(b[j],0);
}
for(i=1;i<=n;i++)printf("%d\n",ans[i]);
}
/*
5
1
a
3
a
ba
cb
3
vba
d
ba
3
ca
da
da
3
as
ba
af
2
4
abc
abcd
a
a
2
abcdef
abcdev
*/
I. Intricate path
留坑。
J. Jumps through the Hyperspace
顯然到每個點的時間越早越好,對於每種傳送門預處理出每種餘數下的最優等待時間即可。
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef pair<int,int>P;
const int N=2010,inf=~0U>>1;
int n,m,st,i,j,a[N],b[N],c[N],d[N],w[N][N];
int f[N];
char g[N][N],op[N];
priority_queue<P,vector<P>,greater<P> >q;
inline void ext(int x,int y){
if(f[x]>y)q.push(P(f[x]=y,x));
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d%d%d",&n,&m,&st);
while(m--){
scanf("%s",op);
int o=op[0];
scanf("%d%d%d%d",&a[o],&b[o],&c[o],&d[o]);
for(i=0;i<c[o];i++){
w[o][i]=inf;
for(j=0;j<c[o];j++)w[o][i]=min(w[o][i],(a[o]*(i+j)+b[o])%c[o]+d[o]+j);
}
}
for(i=1;i<=n;i++)scanf("%s",g[i]+1);
for(i=1;i<=n;i++)f[i]=inf;
ext(1,st);
while(!q.empty()){
P t=q.top();q.pop();
if(f[t.second]<t.first)continue;
for(i=1;i<=n;i++)if(g[t.second][i]!='.')
ext(i,t.first+w[g[t.second][i]][t.first%c[g[t.second][i]]]);
}
if(f[n]==inf)puts("-1");else
printf("%d",f[n]-st);
}
K. King’s island
暴力搜尋出一個上凸殼,然後翻轉拼接起來得到完整的多邊形即可。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1010, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n;
struct B
{
int x, y;
bool operator < (const B & b)const
{
//y/x > b.y/b.x
return y * b.x > x * b.y;
}
};
B p[100000]; int g;
int f[N][N][62];
struct A
{
int x, y, z;
};
bool bingo[60];
vector<B>ans[60];
void getvt(int x, int y, int v, vector<B>&vt, int DX, int DY)
{
if(v == 0)return;
int o = f[x][y][v];
if(f[x - p[o].x][y - p[o].y][v] == o)
{
getvt(x - p[o].x, y - p[o].y, v, vt, DX + p[o].x, DY + p[o].y);
}
else
{
vt.push_back({p[o].x + DX, p[o].y + DY});
getvt(x - p[o].x, y - p[o].y, v - 1, vt, 0, 0);
}
}
void init()
{
for(int i = 1; i <= 200; ++i)
{
for(int j = i + 1; j <= 200; ++j)if(__gcd(i, j) == 1)
{
int W = (i * i + j * j);
int w = sqrt(W);
if(w * w == W)
{
p[++g] = {i, j};
p[++g] = {j, i};
}
}
}
sort(p + 1, p + g + 1);
//printf("%d\n", g);
MS(f, 0);
f[0][0][0] = 1;
for(int i = 0; i <= 500; ++i)
{
for(int j = 0; j <= 500; ++j)
{
for(int v = 29; v >= 0; --v)if(f[i][j][v])
{
//
int k = f[i][j][v];
auto &it = f[i + p[k].x][j + p[k].y][v];
if(it == 0)it = k;
//
for(int k = f[i][j][v] + 1; k <= g; ++k)
{
auto &it = f[i + p[k].x][j + p[k].y][v + 1];
if(it == 0)it = k;
}
if(i == 0 || j == 0)continue;
for(int u = 1; u + v <= 30; ++u)if(f[i][j][u] && f[i][j][u] != f[i][j][v])
{
if(!bingo[u + v])
{
bingo[u + v] = 1;
vector<B>up, down;
getvt(i, j, u, up, 0, 0);
getvt(i, j, v, down, 0, 0);
int x = i;
int y = j;
//printf("%d %d %d\n", u + v, up.size(), down.size());
//puts("up------------");
for(int r = 0; r < up.size(); ++r)
{
x -= up[r].x;
y -= up[r].y;
ans[u + v].push_back({x, y});
//printf("%d %d\n", up[r].x, up[r].y);
}
//puts("down------------");
for(int r = 0; r < down.size(); ++r)
{
x += down[r].x;
y += down[r].y;
ans[u + v].push_back({x, y});
//printf("%d %d\n", down[r].x, down[r].y);
}
//puts("ans------");
for(auto w : ans[u + v])
{
//printf("%d %d\n", w.x, w.y);
}
int pasue = 1;
}
}
}
}
}
for(int i = 1;i <= 30; ++i)
{
//printf("%d\n", bingo[i]);
}
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
init();
while(~scanf("%d", &n))
{
if(n == 3)
{
puts("0 0\n4 3\n-20 21");
continue;
}
for(auto it : ans[n])
{
printf("%d %d\n", it.x, it.y);
}
}
return 0;
}
/*
【trick&&吐槽】
【題意】
【分析】
【時間複雜度&&優化】
28 195
9 15
-116 178
4
20 21
1 -159
-236 -11
-92 6
5
20 50
3 -94
-16 -274
-236 18
-92 35
*/
L. Lexica
無視同一行/同一列的兩個格子的位置關係,只需要在它們不相同時將方案數乘$2$,如此一來只關心每一行/每一列有多少格子沒滿足。
設$f[i][j][S][k]$表示考慮到$(i,j)$,每一列剩餘情況為$S$,第$i$行還有$k$個格子需要填充時的方案數,然後逐格轉移即可。
時間複雜度$O(n3^n)$。
#include<cstdio>
typedef unsigned long long ll;
const int N=18,M=1600000;
int n,m,all,i,j,k,x,y,z,A,B,C,S,o,p[N],mask,cnt[N];
char a[N][N];
int e;
ll f[2][M][3],mul;
int w[M];
inline void clr(){
for(int i=0;i<=mask;i++)for(int j=0;j<3;j++)f[e^1][i][j]=0;
}
inline void nxt(){
//for(int i=0;i<=mask;i++)for(int j=0;j<3;j++)f[i][j]=g[i][j];
}
inline int get(int S,int x){
return S/p[x]%3;
}
void dfs(int x,int y,int z){
if(x==n){
w[y]=z;
return;
}
for(int i=0;i<3;i++)dfs(x+1,y*3+i,z*2+(!!i));
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&n);
m=n+2;
for(i=0;i<m;i++)scanf("%s",a[i]);
mul=1;
for(p[0]=i=1;i<N;i++)p[i]=p[i-1]*3;
all=p[n];
for(i=1;i<=n;i++){
if(a[0][i]!='#'&&a[m-1][i]!='#'&&a[0][i]!=a[m-1][i])mul*=2;
if(a[i][0]!='#'&&a[i][m-1]!='#'&&a[i][0]!=a[i][m-1])mul*=2;
if(a[i][0]!='#')cnt[i]++;
if(a[i][m-1]!='#')cnt[i]++;
if(a[0][i]!='#')mask+=p[i-1];
if(a[m-1][i]!='#')mask+=p[i-1];
}
dfs(0,0,0);
f[0][mask][0]=mul;
for(i=1;i<=n;i++){
clr();
int o=cnt[i];
for(A=0;A<=mask;A++)f[e^1][A][o]=f[e][A][0];
e^=1;
for(j=0;j<n;j++)if(a[i][j+1]=='.'){
clr();
for(S=0;S<=mask;S++){
if(w[S]>>j&1)for(k=0;k<=o;k++)if(f[e][S][k])f[e^1][S-p[j]][k]+=f[e][S][k];
for(k=1;k<=o;k++)if(f[e][S][k])f[e^1][S][k-1]+=f[e][S][k];
}
e^=1;
}
}
printf("%llu",f[e][0][0]);
}
/*
5
##ARRR#
H.#.##S
Y.....E
O.#.#.E
##....E
###.#.E
#XNT#A#
*/
M. Maximal paths
樹形DP求出每個點內部從葉子往上、從上往下的最大數字串即可。需要手寫高精度。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned long long ll;
typedef __int128 lll;
const int N=10000010,M=50;
const ll MO=1000000000000000000ULL;
int n,i;char a[N];
struct P{
ll v[3];
P(){v[0]=v[1]=v[2]=0;}
P operator+(int b){
P c;
for(int i=0;i<3;i++)c.v[i]=v[i];
c.v[0]+=b;
for(int i=0;i<2;i++)if(c.v[i]>=MO){
c.v[i+1]+=c.v[i]/MO;
c.v[i]-=MO;
}
return c;
}
P operator+(const P&b){
P c;
for(int i=0;i<3;i++)c.v[i]=v[i]+b.v[i];
for(int i=0;i<2;i++)if(c.v[i]>=MO){
c.v[i+1]+=c.v[i]/MO;
c.v[i]-=MO;
}
return c;
}
P operator*(int b){
P c;
for(int i=0;i<3;i++)c.v[i]=v[i]*b;
for(int i=0;i<2;i++)c.v[i+1]+=c.v[i]/MO,c.v[i]%=MO;
c.v[2]%=MO;
return c;
}
P operator*(const P&b){
P c;
static lll f[3];
f[0]=f[1]=f[2]=0;
for(int i=0;i<3;i++)if(v[i])for(int j=0;i+j<3;j++)if(b.v[j])f[i+j]+=(lll)v[i]*b.v[j];
for(int i=0;i<2;i++)if(f[i]>=MO)f[i+1]+=f[i]/MO,f[i]%=MO;
if(f[2]>=MO)f[2]%=MO;
for(int i=0;i<3;i++)c.v[i]=f[i];
return c;
}
void up(const P&b){//max=
int i;
for(i=2;~i;i--)if(b.v[i]!=v[i])break;
if(i<0)return;
if(b.v[i]<v[i])return;
for(i=0;i<3;i++)v[i]=b.v[i];
}
void write(){
int i=2;
while(i&&!v[i])i--;
printf("%llu",v[i]);
for(int j=i-1;~j;j--)printf("%018llu",v[j]);
puts("");
}
}f[M],g[M],p[M],ans,ff,gg,mx[M];
int d[M];
unsigned int seed,base;
void dfs(int x,int k){
f[k]=g[k]=mx[k]=P();
d[k]=0;
for(int i=0;i<2;i++){
int y=x<<1|i;
if(y>n)continue;
dfs(y,k+1);
ff=(f[k+1]*10)+((int)a[y]);
gg=g[k+1]+(p[d[k+1]]*((int)a[y]));
mx[k].up((ff*p[d[k]])+g[k]);
mx[k].up((f[k]*p[d[k+1]+1])+gg);
/*if(x==1){
puts("debug");
ff.write();
f[k].write();
}*/
f[k].up(ff);
g[k].up(gg);
d[k]=max(d[k],d[k+1]+1);
/*if(x==1){
puts("debug");
ff.write();
f[k].write();
}*/
}
/* printf("%d:\n",x);
f[k].write();
g[k].write();
mx[k].write();*/
ans=ans+mx[k];
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d%u",&n,&seed);
base=(1U<<31)-1;
p[0].v[0]=1;
for(i=1;i<M;i++)p[i]=p[i-1]*10;
for(i=1;i<=n;i++){
a[i]=((seed&base)>>16)%9+1;
seed=seed*1103515245+12345;
//printf("%d\n",a[i]); i and i/2
}
dfs(1,0);
ans.write();
}