A. City Wall
找规律。
#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() { }
#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 = 0, 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;
int main()
{
while(~scanf("%d",&n)){
int i, typ, sum, j;
typ = 1; sum = 7; i = 12;
while(1){
sum += typ; i ++;
if(sum >= n) break;
int flag = 1;
for(int j = 1; j <= 4; j ++){
sum += typ + 1; i ++;
//printf("%d %d
", sum, i);
if(sum >= n) {flag = 0; break;}
}
if(!flag) break;
sum += typ + 2; i ++;
if(sum >= n) break;
typ ++;
}
if(n >= 8) printf("%d
", i);
else{
int ans;
if(n == 1) ans = 6;
else if(n == 2) ans = 8;
else if(n == 3) ans = 9;
else if(n == 4) ans = 10;
else if(n == 5) ans = 11;
else if(n == 6) ans = 12;
else if(n == 7) ans = 12;
printf("%d
", ans);
}
}
return 0;
}
/*
【trick&&吐槽】
【题意】
【分析】
【时间复杂度&&优化】
*/
B. Domino Colorings
若已经知道了每个格子的颜色,那么可以DP判断是否能由某种骨牌铺成,设$dp[S]$表示轮廓线上$n$个点匹配状态为$S$是否可行即可。
现在不知道每个格子的颜色,那么需要DP这些颜色,设$f[i][j][c][v]$表示考虑到$(i,j)$,轮廓线上$n$个点颜色为$c$,$dp[S]$这个大小为$2^n$的布尔数组取值为$v$时的方案数。
当$n=6$时状态数也只有不到$2000$个,所以可以通过。
#include<cstdio>
#include<map>
using namespace std;
typedef unsigned long long ll;
typedef pair<int,ll>E;
const int P=1000000007;
int n,m,o,i,j,k,x,ans;
map<E,int>f[2];
map<E,int>::iterator it;
inline void up(int&a,int b){a=a+b<P?a+b:a+b-P;}
inline bool check(ll S){
return S&1;
}
int main(){
scanf("%d%d",&n,&m);
f[0][E(0,1)]=1;
for(i=1;i<=m;i++){
for(j=0;j<n;j++){
f[o^1].clear();
for(it=f[o].begin();it!=f[o].end();it++){
int col=it->first.first;
ll dp=it->first.second;
int w=it->second;
int u=col>>j&1;
int l=0;
if(j)l=col>>(j-1)&1;
int ecol=col^(u<<j);
for(k=0;k<2;k++){
int ncol=ecol^(k<<j);
ll ndp=0;
for(x=0;x<1<<n;x++)if(dp>>x&1){
if(x>>j&1){
if(u==k)continue;
ndp|=1ULL<<(x^(1<<j));
continue;
}
ndp|=1ULL<<(x^(1<<j));
if(j&&l!=k)if(x>>(j-1)&1)ndp|=1ULL<<(x^(1<<(j-1)));
}
up(f[o^1][E(ncol,ndp)],w);
}
}
o^=1;
}
}
for(it=f[o].begin();it!=f[o].end();it++)if(check(it->first.second))up(ans,it->second);
printf("%d",ans);
}
C. Counterquestion
暴力枚举$10!$种大小关系,然后求出每种的方案数即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=500;
int n,i,j,m,q[N],id[N],cnt,rk[N];char a[N];
ll f[5000000];
void write(ll S){
static ll w[1000];
for(int i=n-1;i;i--){
w[i]=S%3;
S/=3;
}
for(i=1;i<n;i++){
putchar(a[i]);
putchar(' ');
if(w[i]==0)putchar('=');
if(w[i]==1)putchar('<');
if(w[i]==2)putchar('>');
putchar(' ');
}
putchar(a[n]);
}
int main(){
scanf("%s",a+1);
n=strlen(a+1);
for(i=1;i<=n;i++){
if(!id[a[i]])id[a[i]]=++m;
}
for(i=1;i<=m;i++)q[i]=i;
do{
for(i=1;i<=m;i++)rk[q[i]]=i;
ll cur=0;
for(i=1;i<n;i++){
cur*=3;
if(a[i]==a[i+1])continue;
if(rk[id[a[i]]]<rk[id[a[i+1]]])cur++;
else cur+=2;
}
f[++cnt]=cur;
}while(next_permutation(q+1,q+m+1));
sort(f+1,f+cnt+1);
for(i=1;i<=cnt;i=j){
for(j=i;j<=cnt&&f[i]==f[j];j++);
if(j==i+1){
write(f[i]);
return 0;
}
}
puts("Impossible");
}
D. Galaxy Center
首先假设$A$在$B$外层或同层,不然可以交换$AB$。
若$A$和$B$同层且距离不超过$5$,则此时直接走过去最优。
否则最优方案一定是将$A$往里走一层。
#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() { }
#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 = 40, 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;
char a[N], b[N];
LL v[N];
struct P
{
LL x, y;
}va, vb;
void mul(P &a)
{
++a.x;
a.y *= 3;
}
void div(P &a)
{
--a.x;
a.y /= 3;
}
void add(P &a)
{
++a.y;
if(a.y == v[a.x])a.y -= v[a.x];
}
void sub(P &a)
{
--a.y;
if(a.y < 0)a.y += v[a.x];
}
P know(char s[N])
{
P now = {0, 0};
for(int i = 0; s[i]; ++i)
{
if(s[i] == 'c')
{
mul(now);
}
else if(s[i] == 'g')
{
div(now);
}
else if(s[i] == 's')
{
add(now);
}
else if(s[i] == 'a')
{
sub(now);
}
else {puts("s[i] = ?"); while(1);}
}
return now;
}
void print(P a)
{
printf("%lld %lld
", a.x, a.y);
}
string GO(P a, P b)
{
if(a.x == b.x && a.y == b.y)return "";
string ans = "";
bool swp = 0;
if(a.x < b.x)
{
swp = 1;
swap(a, b);
}
LL by = b.y * v[a.x - b.x];
LL disS = by - a.y; if(disS < 0)disS += v[a.x];
LL disA = a.y - by; if(disA < 0)disA += v[a.x];
bool flag = 0;
if(a.x == b.x)
{
if(disS < disA)
{
if(disS <= 5)
{
while(disS)
{
--disS;
add(a); ans += 's';
}
flag = 1;
}
}
else if(disA < disS)
{
if(disA <= 5)
{
while(disA)
{
--disA;
sub(a); ans += 'a';
}
flag = 1;
}
}
}
if(!flag)
{
if(a.y % 3 == 1)
{
sub(a); ans += 'a';
}
else if(a.y % 3 == 2)
{
add(a); ans += 's';
}
div(a); ans += 'g';
}
ans += GO(a, b);
if(swp)
{
int len = ans.size();
for(int i = 0; i < len / 2; ++i)
{
swap(ans[i], ans[len - 1 - i]);
}
for(int i = 0; i < len; ++i)
{
if(ans[i] == 's')ans[i] = 'a';
else if(ans[i] == 'a')ans[i] = 's';
else if(ans[i] == 'c')ans[i] = 'g';
else if(ans[i] == 'g')ans[i] = 'c';
else {puts("ans[i] = ?"); while(1);}
}
}
return ans;
}
int main()
{
v[0] = 1;
for(int i = 1; i <= 36; ++i)v[i] = v[i - 1] * 3;
while(~scanf("%s%s", a, b))
{
//print(know(a)); print(know(b));
cout << GO(know(a), know(b)) << endl;
}
return 0;
}
/*
【trick&&吐槽】
cccs
cs
cg
cg
cg
ccaaa
ccc
csss
cccsca
cccacs
csss
ccc
cccacs
cccsca
cccs
csscc
csscc
cccs
【题意】
【分析】
【时间复杂度&&优化】
*/
E. IBM 1403
预处理出$f[i][j]$表示模式串第$i$个位置之后第一个字符$j$的位置,对于每一行计算需要的最大时间即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000010;
typedef long long ll;
int L,n,i,j,cur,f[100010][130];
char a[N],b[N];
ll ans;
int main(){
gets(a);
L=strlen(a);
for(i=L-1;~i;i--)f[L][a[i]]=i;
for(i=L-1;~i;i--){
for(j=0;j<130;j++)f[i][j]=f[i+1][j];
f[i][a[i]]=i;
}
while(gets(b)){
n=strlen(b);
int tmp=0;
for(i=0;i<n;i++){
char x=b[i];
if(x==' ')continue;
int nxt=((f[(cur+i)%L][x]-(cur+i))%L+L)%L;
if(nxt>tmp)tmp=nxt;
}
tmp++;
ans+=tmp;
cur=(cur+tmp)%L;
}
printf("%lld",ans);
}
F. Line Tracing
留坑。
G. The Queen and the Knight
当$nleq 30$时,可以$O(n^5)$BFS出所有局面下的最优策略。
当$n>30$时,可以先逼近骑士,然后分类构造。
H. Product of Roots
[egin{eqnarray*}
f(x)&=&prod_{i=1}^n(1+a_ix)\
&=&expleft(sum_{i=1}^nln(1+a_ix)
ight)
end{eqnarray*}]
将$ln(1+a_ix)$泰勒展开,有:
[egin{eqnarray*}
f(x)&=&expleft(sum_{i=1}^nln(1+a_ix)
ight)\
&=&expleft(sum_{i=1}^nsum_{jgeq 1}frac{(-1)^{j+1}}{j}x^ja_i^j
ight)\
&=&expleft(sum_{jgeq 1}frac{(-1)^{j+1}}{j}x^jsum_{i=1}^n a_i^j
ight)\
&=&expleft(sum_{jgeq 1}frac{(-1)^{j+1}}{j}x^jA_j
ight)\
end{eqnarray*}]
对于$g$和$h$同理,则:
[egin{eqnarray*}
g(x)&=&expleft(sum_{jgeq 1}frac{(-1)^{j+1}}{j}x^jB_j
ight)\
h(x)&=&expleft(sum_{jgeq 1}frac{(-1)^{j+1}}{j}x^jsum_{i=1}^nsum_{k=1}^m a_i^jb_k^j
ight)\
&=&expleft(sum_{jgeq 1}frac{(-1)^{j+1}}{j}x^jsum_{i=1}^n a_i^jsum_{k=1}^m b_k^j
ight)\
&=&expleft(sum_{jgeq 1}frac{(-1)^{j+1}}{j}x^jA_jB_j
ight)\
&=&expleft(sum_{jgeq 1}frac{(-1)^{j+1}}{j}x^jC_j
ight)
end{eqnarray*}]
多项式$ln$求出所有$A_i$和$B_i$,令$C_i=A_iB_i$,然后按上式用多项式$exp$计算$h$即可。
时间复杂度$O(nlog n)$。
#include<cstdio>
typedef long long ll;
const int N=262144,K=17;
int n,m,i,k,_;
int a[N+10],b[N+10],c[N+10],tmp[N+10],tmp2[N+10];
int P=998244353,G=3,g[K+1],ng[K+10],inv[N+10],inv2;
inline int pow(int a,int b){int t=1;for(;b;b>>=1,a=(ll)a*a%P)if(b&1)t=(ll)t*a%P;return t;}
inline void NTT(int*a,int n,int t){
for(int i=1,j=0;i<n-1;i++){
for(int s=n;j^=s>>=1,~j&s;);
if(i<j){int k=a[i];a[i]=a[j];a[j]=k;}
}
for(int d=0;(1<<d)<n;d++){
int m=1<<d,m2=m<<1,_w=t==1?g[d]:ng[d];
for(int i=0;i<n;i+=m2)for(int w=1,j=0;j<m;j++){
int&A=a[i+j+m],&B=a[i+j],t=(ll)w*A%P;
A=B-t;if(A<0)A+=P;
B=B+t;if(B>=P)B-=P;
w=(ll)w*_w%P;
}
}
if(t==-1)for(int i=0,j=inv[n];i<n;i++)a[i]=(ll)a[i]*j%P;
}
void getinv(int*a,int*b,int n){
if(n==1){b[0]=pow(a[0],P-2);return;}
getinv(a,b,n>>1);
int k=n<<1,i;
for(i=0;i<n;i++)tmp[i]=a[i];
for(i=n;i<k;i++)tmp[i]=b[i]=0;
NTT(tmp,k,1),NTT(b,k,1);
for(i=0;i<k;i++){
b[i]=(ll)b[i]*(2-(ll)tmp[i]*b[i]%P)%P;
if(b[i]<0)b[i]+=P;
}
NTT(b,k,-1);
for(i=n;i<k;i++)b[i]=0;
}
inline void getln(int*a,int*b,int n){
getinv(a,tmp2,n);
int k=n<<1,i;
for(i=0;i<n-1;i++)b[i]=(ll)a[i+1]*(i+1)%P;
for(i=n-1;i<k;i++)b[i]=0;
NTT(b,k,1),NTT(tmp2,k,1);
for(i=0;i<k;i++)b[i]=(ll)b[i]*tmp2[i]%P;
NTT(b,k,-1);
for(i=n-1;i;i--)b[i]=(ll)b[i-1]*inv[i]%P;b[0]=0;
}
void getexp(int*a,int*b,int n){
if(n==1){b[0]=1;return;}
getexp(a,b,n>>1);
getln(b,tmp,n);
int k=n<<1,i;
for(i=0;i<n;i++){tmp[i]=a[i]-tmp[i];if(tmp[i]<0)tmp[i]+=P;}
if((++tmp[0])==P)tmp[0]=0;
for(i=n;i<k;i++)tmp[i]=b[i]=0;
NTT(tmp,k,1),NTT(b,k,1);
for(i=0;i<k;i++)b[i]=(ll)b[i]*tmp[i]%P;
NTT(b,k,-1);
for(i=n;i<k;i++)b[i]=0;
}
int main(){
for(g[K]=pow(G,(P-1)/N),ng[K]=pow(g[K],P-2),i=K-1;~i;i--)g[i]=(ll)g[i+1]*g[i+1]%P,ng[i]=(ll)ng[i+1]*ng[i+1]%P;
for(inv[1]=1,i=2;i<=N;i++)inv[i]=(ll)(P-inv[P%i])*(P/i)%P;inv2=inv[2];
scanf("%d%d%d",&n,&m,&_);
k=131072;
for(i=0;i<=n;i++)scanf("%d",&a[i]);
getln(a,c,k);
for(i=0;i<k;i++)a[i]=c[i],c[i]=0;
for(i=0;i<=m;i++)scanf("%d",&b[i]);
getln(b,c,k);
for(i=0;i<k;i++)a[i]=1LL*a[i]*c[i]%P,b[i]=0;
for(i=0;i<k;i+=2)a[i]=(P-a[i])%P;
for(i=1;i<k;i++)a[i]=1LL*a[i]*i%P;
getexp(a,b,k);
for(i=0;i<_;i++)printf("%d ",b[i]);
return 0;
}
I. Safe Landing
按题意模拟。
#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() { }
#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 = 1e5 + 10, 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;
char s[N];
bool v[128];
int main()
{
while(~scanf("%s",s))
{
MS(v, 0);
int cnt = 0;
for(int i = 0; s[i]; ++i)
{
if(!v[s[i]])++cnt;
v[s[i]] = 1;
}
if(cnt <= 1)puts("X");
else if(cnt == 3)
{
if(!v['N'])puts("N");
else if(!v['S'])puts("S");
else if(!v['W'])puts("W");
else if(!v['E'])puts("E");
else while(1);
}
else if(cnt == 2)
{
if(v['N'] && v['W']) puts("SE");
else if(v['N'] && v['E'])puts("SW");
else if(v['S'] && v['W']) puts("NE");
else if(v['S'] && v['E'])puts("NW");
else puts("X");
}
else while(1);
}
return 0;
}
/*
【trick&&吐槽】
【题意】
【分析】
【时间复杂度&&优化】
*/
J. Perfect Square
取$20$个大质数,然后检查$x^2mod p=n$是否有解即可。
根据二次剩余,这等价于$n^{frac{p-1}{2}}mod p=1$。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int N=1000010;
int n,i,cnt;char a[N];
bool isprime(int n){
for(int i=2;i<=n/i;i++)if(n%i==0)return 0;
return 1;
}
ll powmod(ll a,ll b,ll P){
ll t=1;
for(;b;b>>=1,a=a*a%P)if(b&1)t=t*a%P;
return t;
}
bool work(ll n,ll p){
if(n==0||n==1)return 1;
if(powmod(n,p>>1,p)!=1)return 0;
return 1;
}
bool check(int P){
ll ret=0;
for(int i=1;i<=n;i++)ret=(ret*10+a[i]-'0')%P;
return work(ret,P);
}
int main(){
scanf("%s",a+1);
n=strlen(a+1);
for(i=1000000000;;i++)if(isprime(i)){
if(!check(i))return puts("No"),0;
cnt++;
if(cnt>=20)return puts("Yes"),0;
}
}