https://vjudge.net/contest/321593
今天打了2018CCPC的网络赛,整个人毫无状态,极其颓废。
接下来按照题目难度顺序整理(学习):
D Find Integer
给出a和n,求使(a^n+b^n=c^n)成立的b和c,无解则输出-1 -1
虽说是裸的费马定理的板子,但是我真的不知道啊……
费马定理: (n>2)时,(a^n+b^n=c^n)无解
(n=1)时,(a+b=c),固输一个1和1+a即可
(n=2)时,(a^2+b^2=c^2),勾股数:
(a)为奇数时,(tmp=a/2;) (b=(tmp+1)*tmp*2;) (c=b+1;)
(a)为偶数时,(tmp=a/2-1;) (b=(tmp+2)*tmp;) (c=b+2;)
所以总之,这就是个特判固输题,但是……
#include<cstdio>
typedef long long ll;
using namespace std;
ll t,n,a,b,c,tmp;
int main()
{
scanf("%lld",&t);
while (t--)
{
scanf("%lld%lld",&n,&a);
if (n==1) printf("1 %lld
",a+1);
else if (n>2 || n==0) printf("-1 -1
");
else
{
if (a&1)
{
tmp=a/2;
b=(tmp+1)*tmp*2;
c=b+1;
}
else
{
tmp=a/2-1;
b=(tmp+2)*tmp;
c=b+2;
}
printf("%lld %lld
",b,c);
}
}
return 0;
}
I Tree and Permutation
给出一个点数为n的树,求1~n的所有全排列对应到树上相应位置后,从1-2-...-n经过的边权的和
初步思路没有问题,求一条边两端分别有多少点,但是对于次数的计算不太明了。
事实上,如果这条边的一端为(M)个点,另一端为(N-M)个点,则经过他的次数就是(M*(N-M)),再算上不同的全排列:这两个点有(N-1)种,除了这两个点以外有((N-2)!)种,所以这条边造成的贡献就总共有(L*M*(N-M)*(N-1)!),其中(L)为该边的边长
那么每条边的贡献出来了之后,我们只要dfs求端点个数,在过程中求出答案就可以了
#include<cstdio>
#include<cstring>
#define N 100010
#define P 1000000007
typedef long long ll;
using namespace std;
int n,head[N],cnt,son[N];
ll sum;
struct hhh
{
int nxt,to,w;
}e[N*2];
void add(int x,int y,int z)
{
e[cnt].nxt=head[x];
e[cnt].to=y;
e[cnt].w=z;
head[x]=cnt++;
}
void dfs(int x,int f)
{
for (int i=head[x],v;i;i=e[i].nxt)
{
v=e[i].to;
if (v==f) continue;
dfs(v,x);
sum+=1LL*2*son[v]*(n-son[v])%P*e[i].w%P;
sum%=P;
son[x]+=son[v];
}
son[x]++;
}
ll get(ll x)
{
ll s=1;
for (int i=2;i<=x;i++)
s=s*i%P;
return s;
}
int main()
{
while (~scanf("%d",&n))
{
memset(head,0,sizeof(head));
memset(son,0,sizeof(son));
cnt=1;
sum=0;
for (int i=1,x,y,z;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dfs(1,0);
(sum*=get(n-1))%=P;
printf("%lld
",sum);
}
return 0;
}
C Dream
要求重定义+和*,使得((m+n)^p=m^p+n^p)且存在(q<p)使得({q^k | 0<k<p,k in Z} = {k | 0<k<p , k in Z})
其中p是质数。
因为p是质数,考虑费马小定理,((m+n)^{p-1} equiv 1 (mod p)),所以((m+n)^p equiv m+n (mod p))
同样的,(m^p=m),(n^p=n),所以(m^p+n^p=m+n),所以((m+n)^p=m^p+n^p)可得。
综上,重定义的+和就是在(mod p)意义下的+和
(这怎么想到费马小定理嘛……
#include<cstdio>
using namespace std;
int t,p;
int main()
{
scanf("%d",&t);
while (t--)
{
scanf("%d",&p);
for (int i=0;i<p;i++)
for (int j=0;j<p;j++)
printf("%d%c",(i+j)%p,"
"[j==p-1]);
for (int i=0;i<p;i++)
for (int j=0;j<p;j++)
printf("%d%c",i*j%p,"
"[j==p-1]);
}
return 0;
}