A
Decription:
Sample Input:
5
6 6
7 7
8 8
9 9
10 1
Sample Output:
666666
7777777
88888888
1755646
112866758
思路:很显然从数据规模和这些诡异的数字轻松得知此题是数论,那么怎么做呢,首先我们要输出的结果是kkkkkk这个数,那么我们可以把它化成k*(
1
0
0
10^0
100+
1
0
1
10^1
101+…+
1
0
n
10^n
10n),那么很显然 赛时没看出来,可以用等比数列化简(
S
n
S_n
Sn=
a
1
(
q
n
−
1
)
q
−
1
\frac{a_1(q^n-1)}{q-1}
q−1a1(qn−1))
a
1
a_1
a1为首项,q为公比。然后用逆元mod一下下就好了。
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
const ll mod=998244353;
ll n,k,ny,t;
ll ksm(ll x,ll y)
{
ll res=1;
while(y)
{
if(y&1) res*=x,res%=mod;
x=x*x%mod,y>>=1;
}
return res;
}
int main()
{
scanf("%lld",&t);
ny=ksm(9,mod-2);
while(t--)
{
scanf("%lld%lld",&n,&k);
ll a1=ksm(10,n)-1;
printf("%lld\n",k*(a1*ny)%mod);
}
return 0;
}
B
Decription:
Input
Output
Sample Input:
6 8 2
1 4
4 5
3 5
3 6
1 5
2 4
2 6
2 5
Sample Output:
3
Hint
思路
这题呀,可以看到,初一看缩点Tatjan,再一看似乎不用那么复杂,首先可以先把>k的编号先连上,再连<=k的编号,在此过程中用并查集去看两个点的父亲是否相同,如果是则是一个环,记录答案,不是就
连起来。
代码
#include<iostream>
#include<cstdio>
#define N 2000000
using namespace std;
int n,m,k,x[N+1],y[N+1],f[N+1],ans;
int fd(int xx)
{
if(xx==f[xx]) return xx;
return f[xx]=fd(f[xx]);
}
int qread()
{
int x=0;
char c=getchar();
while(c>'9'||c<'0') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x;
}
int main()
{
n=qread(),m=qread(),k=qread();
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++)
{
x[i]=qread(),y[i]=qread();
if(x[i]>k&&y[i]>k) f[fd(x[i])]=fd(y[i]);
}
for(int i=1;i<=m;i++)
{
if(x[i]<=k||y[i]<=k)
{
if(fd(x[i])==fd(y[i])) ans++;
else f[fd(x[i])]=fd(y[i]);
}
}
printf("%d",ans);
return 0;
}
C
Decription:
一棵树删去任意条边,可以得到若干棵新树。
若使让每棵新树的节点数相同。问有多少种方法分割这棵树。
设给出的树的结点数为n,并给出n-1条边
Input
第一行一个正整数N,表示这棵树的结点总数。
接下来N-1行,每行两个数字X,Y表示编号为X的结点与编号为Y的结点相连。结点编号的范围为[1,N]。
Output
一个整数,表示方案数。注意,不砍去任何一条边也算作一种方案。
Sample Input:
输入样例
Sample Output:
6
1 2
2 3
2 4
4 5
5 6
Data Constraint
对于40%的数据,N ≤ 15
对于60%的数据,N ≤ 10^5
对于100%的数据,N ≤ 10^6
数据规模非常大,请使用高效的读入方式
思路
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define N 1000000
#define ll long long
using namespace std;
int n,x,y,con[N];
int he[N<<2],nxt[N<<2],cnt,to[N<<2],js1,js2,ans;
void add(int u,int v)
{
cnt++;
nxt[cnt]=he[u];
he[u]=cnt;
to[cnt]=v;
}
void build_tree(int pre,int now)
{
for(int i=he[now];i;i=nxt[i])
{
int g=to[i];
if(g==pre) continue;
build_tree(now,g);
con[now]+=con[g];
}
con[now]++;
}
int qread()
{
char cc='o';
int x=0,pd=1;
while(cc>'9'||cc<'0')
{
cc=getchar();
if(cc=='-') pd=-1;
}
while(cc<='9'&&cc>='0')
{
x=(x<<3)+(x<<1)+cc-'0';
cc=getchar();
}
return x*pd;
}
int main()
{
n=qread();
for(int i=1;i<=n-1;i++)
{
x=qread(),y=qread();
add(x,y),add(y,x);
}
build_tree(0,1);
for(int i=1;i<=sqrt(n);i++)
{
if(n%i==0)
{
js1=0,js2=0;
for(int j=1;j<=n;j++)
{
if(con[j]%i==0) js1++;
if(con[j]%(n/i)==0) js2++;
}
if(js1==n/i) ans++;
if(js2==n/(n/i)) ans++;
if(i==n/i) ans--;
}
}
printf("%d",ans);
return 0;
}
D
Decription:
多个询问,
每个询问给出长度为n的2个序列a,b
每次可以对1<i<n的ai进行操作,
操作后, a i ′ = a i + 1 + a i − 1 − a i a^{'}_i=a_{i+1}+a_{i-1}-a_i ai′=ai+1+ai−1−ai
问能否通过若干次操作,使得序列a变成 b
Input
给出询问数T
第一行一个正整数n
第二行给出序列a
第三行给出序列b
Output
是否能转变,输出Yes或者No,每个询问对应一行
Sample Input:
Sample Input 1
1
4
7 2 4 12
7 15 10 12
Sample Output 2
1
3
4 4 4
1 2 3
Sample Output:
Sample Output 1
Yes
Sample Output 2
No
Data Constraint
20%:2<=n<=10
100%:2<=n<=1e5,0<=ai,bi<=2e9,T<=10
思路:
赛时竟没看出来是道大水题??
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define N 100000
#define ll long long
using namespace std;
int t,n,a[N+1],c[N+1],b[N+1],d[N+1];
bool flag;
int qread()
{
char cc='o';
int x=0,pd=1;
while(cc>'9'||cc<'0')
{
cc=getchar();
if(cc=='-') pd=-1;
}
while(cc<='9'&&cc>='0')
{
x=(x<<3)+(x<<1)+cc-'0';
cc=getchar();
}
return x*pd;
}
int main()
{
t=qread();
while(t--)
{
flag=0;
n=qread();
for(int i=1;i<=n;i++) a[i]=qread(),c[i]=a[i]-a[i-1];
for(int i=1;i<=n;i++) b[i]=qread(),d[i]=b[i]-b[i-1];
sort(c+1,c+n+1);
sort(d+1,d+n+1);
for(int i=1;i<=n;i++)
{
if(c[i]!=d[i])
{
flag=1;
break;
}
}
if(flag) putchar('N'),putchar('o');
else putchar('Y'),putchar('e'),putchar('s');
putchar('\n');
}
return 0;
}