# Codeforces Round #566 Div. 2

A：n是奇数无解，是偶数为2n/2

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n;
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
if (n&1) cout<<0;
else
{
ll ans=1;
for (int i=1;i<=n/2;i++) ans*=2;
cout<<ans;
}
return 0;
//NOTICE LONG LONG!!!!!
}


B：随便做。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 510
char getc(){char c=getchar();while (c!='.'&&c!='*') c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,a[N][N];
signed main()
{
int qwq=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
char c=getc();
if (c=='.') a[i][j]=0;
else a[i][j]=1,qwq++;
}
bool flag=0;int cnt=0,tot=0;
for (int i=2;i<n;i++)
for (int j=2;j<m;j++)
if (a[i][j]&&a[i-1][j]&&a[i][j-1]&&a[i+1][j]&&a[i][j+1])
{
cnt++;if (cnt>1) {cout<<"NO";return 0;}
tot++;
for (int x=i-1;x>=1;x--) if (a[x][j]) tot++;else break;
for (int x=i+1;x<=n;x++) if (a[x][j]) tot++;else break;
for (int x=j-1;x>=1;x--) if (a[i][x]) tot++;else break;
for (int x=j+1;x<=m;x++) if (a[i][x]) tot++;else break;
}
if (cnt==0) cout<<"NO";
else if (tot==qwq) cout<<"YES";
else cout<<"NO";
return 0;
//NOTICE LONG LONG!!!!!
}


C：码码码。求出每个单词元音个数及最后一个元音。然后看只考虑第二列单词的话最多能配多少对。最后把一些第二列中的单词移到第一列即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 100010
char getc(){char c=getchar();while (c!='.'&&c!='*') c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n;
struct data
{
string s;int m,x,y;
bool operator <(const data&a) const
{
return x<a.x||x==a.x&&y<a.y;
}
}a[N],b[N];
bool flag[N];
string ans[N][2][2];
signed main()
{
std::ios::sync_with_stdio(false);
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i].s;a[i].m=a[i].s.length();
for (int j=0;j<a[i].m;j++)
{
if (a[i].s[j]=='a') a[i].x++,a[i].y=1;
if (a[i].s[j]=='e') a[i].x++,a[i].y=2;
if (a[i].s[j]=='i') a[i].x++,a[i].y=3;
if (a[i].s[j]=='o') a[i].x++,a[i].y=4;
if (a[i].s[j]=='u') a[i].x++,a[i].y=5;
}
}
sort(a+1,a+n+1);
int s=0;
for (int i=1;i<=n;i++)
{
int t=i;
while (t<n&&a[i].x==a[t+1].x&&a[i].y==a[t+1].y) t++;
s+=t-i+1>>1;
i=t;
}
int s2=0;
for (int i=1;i<=n;i++)
{
int t=i;
while (t<n&&a[i].x==a[t+1].x) t++;
s2+=t-i+1>>1;
i=t;
}
int m=min(s,s2/2);cout<<m<<endl;int tmp=0;
for (int i=1;i<n;i++)
if (!flag[i]&&a[i].x==a[i+1].x&&a[i].y==a[i+1].y)
{
flag[i]=flag[i+1]=1,tmp++;
ans[tmp][0][1]=a[i].s,ans[tmp][1][1]=a[i+1].s;
if (tmp==m) break;
}
int u=0;
for (int i=1;i<=n;i++) if (!flag[i]) b[++u]=a[i];
int x=1;
for (int i=1;i<=m;i++)
{
while (b[x].x!=b[x+1].x) x++;
ans[i][0][0]=b[x].s,ans[i][1][0]=b[x+1].s;
x+=2;
cout<<ans[i][0][0]<<' '<<ans[i][0][1]<<endl;
cout<<ans[i][1][0]<<' '<<ans[i][1][1]<<endl;
}
return 0;
//NOTICE LONG LONG!!!!!
}


D：有各种麻烦的做法。sol的做法似乎比较清真。找到一条直径。直径的两端点可能恰好有一个可以作为根，先check一下。如果都不行，check一下直径中点（显然这是唯一一个可能成为根的非叶节点）。还是不行的话，注意到如果存在合法的根，其与直径中点之间一定是一条链连接，因为一旦有分叉，之前找到的不可能是直径。称与直径中点之间是一条链连接的点为合法点。如果只有一个合法点，直接check即可，否则如果仍存在合法根，树将形成一根扫把，找的离直径中点最近的合法点check即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,p[N],t,deep[N],degree[N],fa[N],f[N],root;
bool flag[N];
struct data{int to,nxt;
}edge[N<<1];
void dfs(int k,int from)
{
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from)
{
deep[edge[i].to]=deep[k]+1;
fa[edge[i].to]=k;
dfs(edge[i].to,k);
}
}
bool work(int k,int from)
{
if (!f[deep[k]]) f[deep[k]]=degree[k];
else if (degree[k]!=f[deep[k]]) return 0;
bool flag=1;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from) flag&=work(edge[i].to,k);
return flag;
}
void check(int k){if (k>n) return;memset(f,0,sizeof(f));deep[k]=0;dfs(k,k);if (work(k,k)) {cout<<k;exit(0);}}
void getnb(int k,int from)
{
flag[k]=1;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&degree[edge[i].to]<=2) getnb(edge[i].to,k);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
for (int i=1;i<n;i++)
{
degree[x]++,degree[y]++;
}
dfs(1,1);
for (int i=1;i<=n;i++) if (deep[i]>deep[root]) root=i;
check(root);
int x=0;
for (int i=1;i<=n;i++) if (deep[i]>deep[x]) x=i;
check(x);
if (deep[root]%2==0)
{
check(root);
for (int _=deep[x]/2;_--;_) x=fa[x];
check(x);
getnb(x,x);
int t=n+1;deep[t]=n;
for (int i=1;i<=n;i++) if (flag[i]&&i!=x&&deep[i]<deep[t]&&degree[i]==1) t=i;
check(t);
}
cout<<-1;
return 0;
//NOTICE LONG LONG!!!!!
}


E：对式子取对数后变为线性递推，矩阵快速幂即可。当然也可以直接递推每个数的贡献。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 100010
#define P 1000000007
#define g 5
#define int long long
char getc(){char c=getchar();while (c!='.'&&c!='*') c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
map<int,int> f;
int ksm(int a,int k)
{
int s=1;
for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
return s;
}
int inv(int a){return ksm(a,P-2);}
int BSGS(int a,int b,int p)
{
int block=sqrt(p),t=1;//cout<<a<<' '<<b<<' '<<p<<endl;
f.clear();
for (int i=0;i<block;i++)
{
if (f.find(t)==f.end()) f[t]=i;
if (t==b) return i;
t=1ll*t*a%p;
}
int v=t;
for (int i=1;i<=(p-1)/block;i++)
{
if (f.find(1ll*b*inv(t)%p)!=f.end()) return i*block+f[1ll*b*inv(t)%p];
t=1ll*t*v%p;
}
return -1;
}
ll n,f1,f2,f3,c;
struct matrix
{
int n,a[5][5];
matrix operator *(const matrix&b) const
{
matrix c;c.n=n;memset(c.a,0,sizeof(c.a));
for (int i=0;i<n;i++)
for (int j=0;j<b.n;j++)
for (int k=0;k<b.n;k++)
c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j])%(P-1);
return c;
}
}F,a;
signed main()
{
std::ios::sync_with_stdio(false);
cin>>n>>f1>>f2>>f3>>c;c=1ll*c*c%P;
f1=BSGS(g,f1,P);
f2=BSGS(g,f2,P);
f3=BSGS(g,f3,P);
c=BSGS(g,c,P);
F.n=1;F.a[0][0]=c,F.a[0][1]=c,F.a[0][2]=f1,F.a[0][3]=f2,F.a[0][4]=f3;
a.n=5;
a.a[0][0]=1;a.a[0][1]=1;
a.a[1][1]=1;a.a[1][4]=1;
a.a[2][4]=1;
a.a[3][2]=1;a.a[3][4]=1;
a.a[4][3]=1;a.a[4][4]=1;
n-=3;for (;n;n>>=1,a=a*a) if (n&1) F=F*a;
cout<<ksm(g,F.a[0][4]);
return 0;
//NOTICE LONG LONG!!!!!
}


F：没意思不看了。

小小小小号。result：rank 18 rating +194

posted @ 2019-06-16 10:54  Gloid  阅读(219)  评论(0编辑  收藏  举报