被暴打了。
会先写比赛中过题数100+的题目,其他的以后再补。
施工中,未完待续…
一开始想到的是对比到lcm(|a|,|b|),意料之中T了。
后来脑补了一种方法,把较长的字符串x2,然后把较短的字符串xN,直到超过翻倍后的长字符串,以展现出循环中两个字符串所有的特性,拿到了AC。
至于正确的解法,要使用到 The Periodicity Lemma,详见叉姐知乎:
A note on the proof of the Periodicity Lemma
事实上只需要微调一下T掉的代码,把lcm(|a|,|b|)改成|a|+|b|+gcd(|a|,|b|),就是正解了。
#include
using namespace std;
string a,b;
int la,lb;
int gcd(int a,int b)
{
return b ? gcd(b,a%b) : a;
}
int main()
{
while(cin>>a>>b)
{
la=a.length(),lb=b.length();
int cnt=0,maxcnt=la+lb+gcd(la,lb);
for(int i=0,j=0;;i++,j++)
{
if(a[i]<b[j])
{cout<<"<"<<endl;break;}
if(a[i]>b[j])
{cout<<">"<<endl;break;}
if(i+1==la) i=-1;
if(j+1==lb) j=-1;
cnt++;
if(cnt==maxcnt)
{cout<<"="<<endl;break;}
}
}
}
看到数论直接懵。
正解中提到了Wallis’ integrals和伽马函数之类,没有看懂,浏览其他博客时还看到了贝塔函数和分部积分之类的方法,先挖个坑,以后再填(大概)。
个人的想法还是通过找规律获得(n!)^2/(2n+1)!的通式,计算通式时会用到快速幂,逆元,费马小定理,具体原理在《挑战》P122和P291有解释。
#include
#define int long long
using namespace std;
const int N=2e6+7;
const int mod=998244353;
int fac[N];
int mod_pow(int x,int n)
{
int res=1;
while(n>0)
{
if(n&1)
res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
signed main()
{
int n;
fac[1]=1;
for(int i=2;i<N;i++)
fac[i]=fac[i-1]*i%mod;
while(cin>>n)
cout<<fac[n]*fac[n]%mod*mod_pow(fac[2*n+1],mod-2)%mod<<endl;
}
套 模 板!!!
如果d=1,就是标准的一般图完美匹配,求个最大匹配判断一下就行,但是这题遇到d=2的情况需要分点。一般图最大匹配两种解法,一种是最常见到的带花树,还有一种是Tutte矩阵,《挑战》上带花树提都没提,就花了半页告诉你用Tutte矩阵算,于是因为没学过线代而看不懂的我直接跳过了。。。
考场上无论是出于模板长度还是运行效率,理所当然的会选择Tutte矩阵,不过作为学习,还是顺带套个带花树的代码。
叉姐Tutte矩阵模板:
#include
const int N = 50;
const int M = 100;
const int MOD = 1e9 + 7;
int inverse(int a)
{
return a == 1 ? 1
: static_cast<uint64_t>(MOD - MOD / a) * inverse(MOD % a) % MOD;
}
template<int V>
int tutte(int n, const std::vector<std::pair<int, int>> &edges, int seed)
{
static int mat[V][V];
memset(mat, 0, sizeof(mat));
std::mt19937 gen(seed);
std::uniform_int_distribution<int> dist(1, MOD - 1);
for (auto &&e : edges)
{
auto x = dist(gen);
mat[e.first][e.second] = x;
mat[e.second][e.first] = MOD - x;
}
int rank = 0;
for (int j = 0; j < n; ++j)
{
int pivot = rank;
while (pivot < n && !mat[pivot][j])
{
pivot++;
}
if (pivot < n)
{
for (int k = 0; k < n; ++k)
{
std::swap(mat[rank][k], mat[pivot][k]);
}
const uint64_t inv = inverse(mat[rank][j]);
for (int i = rank + 1; i < n; ++i)
{
if (mat[i][j])
{
const uint64_t tmp = inv * mat[i][j] % MOD;
for (int k = j; k < n; ++k)
{
mat[i][k] += MOD - tmp * mat[rank][k] % MOD;
if (mat[i][k] >= MOD)
{
mat[i][k] -= MOD;
}
}
}
}
rank++;
}
}
return rank;
}
#ifndef NO_MAIN
int deg[N];
int main()
{
int n, m;
while (scanf("%d%d", &n, &m) == 2)
{
int demand = 0;
for (int i = 0; i < n; ++i)
{
scanf("%d", deg + i);
demand += deg[i];
}
std::vector<std::pair<int, int>> edges;
for (int i = 0, a, b; i < m; ++i)
{
scanf("%d%d", &a, &b);
a--, b--;
if (deg[a] == 2)
{
std::swap(a, b);
}
if (deg[a] == 2)
{
edges.emplace_back(a << 1 | 0, n + i << 1 | 0);
edges.emplace_back(a << 1 | 1, n + i << 1 | 0);
edges.emplace_back(b << 1 | 0, n + i << 1 | 1);
edges.emplace_back(b << 1 | 1, n + i << 1 | 1);
edges.emplace_back(n + i << 1 | 0, n + i << 1 | 1);
demand += 2;
}
else if (deg[b] == 2)
{
edges.emplace_back(a << 1, b << 1 | 0);
edges.emplace_back(a << 1, b << 1 | 1);
}
else
{
edges.emplace_back(a << 1, b << 1);
}
}
puts(tutte<(N + M) << 1>(n + m << 1, edges, 0) == demand ? "Yes" : "No");
}
}
#endif
带花树:
正在写...