11.5 解题报告

T1

考场用时:\(30\) min
期望得分:\(100\) pts
实际得分:\(100\) pts
这题只需要知道一个结论:\(\sum_{d|i} \varphi(d)=i\),问题就迎刃而解了。

T2

考场用时:\(1\) h
期望得分:\(100\) pts
实际得分:\(0\) pts
这题保证无环,直接拓扑就行,考场想当然的码上了个BFS。

#include<bits/stdc++.h>
#define ll long long
#define int long long
//#define ull unsigned long long
#define lc(k) k<<1
#define rc(k) k<<1|1
#define lb lower_bound
#define orz cout<<"gzn ak ioi\n"
const int MAX=1e6+10;
const int MOD=1e9+7;
using namespace std;
inline char readchar() {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
	int res = 0, f = 0;
	char ch = readchar();
	for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
	for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
	return f ? -res : res;
}
inline void write(int x) {
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n,m,w[MAX],head[MAX],cnt;
struct node{int u,v,net;}e[MAX];
void add(int u,int v){
	e[++cnt]=(node){u,v,head[u]};
	head[u]=cnt;
	return ;
}
queue<int> q;
int dis[MAX],rd[MAX];
void bfs(){
	for(int i=1;i<=n;i++) if(!rd[i]) q.push(i);
	memset(dis,0x3f,sizeof dis);
	dis[1]=0;
	while(!q.empty()){
		int f=q.front();q.pop();
//		cout<<f<<endl;
		for(int i=head[f];i;i=e[i].net){
			int v=e[i].v;
			dis[v]=min(dis[v],max(dis[f],w[v]));
			rd[v]--;
			if(!rd[v]) q.push(v);
		}
	}
	return ;
}
signed main(){
//	freopen("conceal.in","r",stdin);
//	freopen("conceal.out","w",stdout);
	n=read(),m=read();
	for(int i=1;i<=n;i++) w[i]=read();
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		add(u,v);rd[v]++;
	}
	bfs();
//	for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
	cout<<dis[n];
	return 0;
}

T3

考场用时:\(1\) h
期望得分:\(100\) pts
实际得分:\(100\) pts
这题不难发现,只有当 \(i\ge a \land i\mod a<b\) 时,小 \(X\) 才会赢,所以求出剩余系个数直接 \(O(1)\) 计算即可,注意边界。

#include<bits/stdc++.h>
#define ll long long
#define int long long
//#define ull unsigned long long
#define lc(k) k<<1
#define rc(k) k<<1|1
#define lb lower_bound
#define orz cout<<"gzn ak ioi\n"
const int MAX=1e6+10;
const int MOD=1e9+7;
using namespace std;
inline char readchar() {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
	int res = 0, f = 0;
	char ch = readchar();
	for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
	for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
	return f ? -res : res;
}
inline void write(int x) {
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
/*
i>=a&&i%a<b X赢
*/
signed main(){
//	freopen("deception.in","r",stdin);
//	freopen("deception.out","w",stdout);
	int T=read();
	while(T--){
		int n=read(),a=read(),b=read();
//		if(a==0) a=1;
		int t=n/a;
//		cout<<t<<" "<<n%a<<" "<<b<<endl;
		if(!t) puts("0");
		else write((t-1)*(min(a-1,b-1)+1)+(min(n%a,b-1)+1)),putchar('\n');
	}
	return 0;
}

T4

考场用时:\(2\) h
期望得分:\(50\) pts
实际得分:\(0\) pts
考场一直在试图推式子,但是没能推出来,最后十分钟匆匆忙忙敲上的暴力还忘了取模,应该先把暴力写好,最后 \(10\) min检查一下前面的防止挂分。
这题就是推式子:
我们有方差公式的一个变形

\[S^2=\frac{1}{n}(\sum_{i=1}^n a_i^2-\frac{1}{n}(\sum_{i=1}^{n} a_i)^2) \]

\(b_i\) 表示原集合的子集 \(i\) 的元素和,则根据题意有:

\[S^2=\frac{1}{2^n}(\sum_{i=0}^{2^n} b_i^2-\frac{1}{2^n}(\sum_{i=0}^{2^n} b_i)^2) \]

先来推第二部分:

不难发现,对于所有的 \(a_i\),它出现的次数为 \(\sum_{i=0}^{n-1} \binom{n-1}{i}=2^{n-1}\),所以这个式子等于:

\[\frac{1}{2^n}\times 2^{2n-2} (\sum_{i=1}^{n} a_i)^2 \]

\(S_1=\sum_{i=1}^n a_i\)

\[=2^{n-2}S_1^2 \]

再来考虑第一部分,发现对于它的展开式只有平方项和交叉项,对于平方项,显然每次出现,都会且仅会带来一个平方项,所以对于一个数 \(x\),它的平方项个数就是它的出现次数 \(2^{n-1}\),而对于交叉项,考虑 \(x\)\(y\) 的交叉项,这实际上是固定两个数,于是 \(2\times \sum_{i=0}^{n-2} \binom{n-2}{i}=2^{n-1}\),当然也可以理解为:交叉项与平方项本质相同,所以出现个数也一致。

那么现在写一下总的式子:

\[S^2=\frac{1}{2^n}(2^{n-1}\sum_{i=1}^n\sum_{j=i}^{n}a_i\times a_j-2^{n-2}S_1^2) \]

并按照要求对上式乘以 \(4^n\),得到答案即为:

\[2^{2n-2}(\sum_{i=1}^n a_i^2) \]

复杂度 \(O(n)\)

#include<bits/stdc++.h>
#define ll long long
#define int long long
//#define ull unsigned long long
#define lc(k) k<<1
#define rc(k) k<<1|1
#define lb lower_bound
#define orz cout<<"gzn ak ioi\n"
const int MAX=1e6+10;
const int MOD=1e9+7;
using namespace std;
inline char readchar() {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
	int res = 0, f = 0;
	char ch = readchar();
	for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
	for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
	return f ? -res : res;
}
inline void write(int x) {
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int ksm(int ds,int zs){
	int ret=1;
	while(zs){
		if(zs&1) ret=ret*ds%MOD;
		zs>>=1;ds=ds*ds%MOD;
	}
	return ret;
}
signed main(){
	int n=read(),sum=0;
	for(int i=1;i<=n;i++){
		int x=read();
		sum=(sum+x*x)%MOD;
	}
	cout<<(ksm(2,2*n-2)*sum%MOD);
	return 0;
}
posted @ 2022-11-06 20:14  wapmhac  阅读(17)  评论(0编辑  收藏  举报