10.24解题报告

T1

用时:约 \(100\) min

这个题用的时间最多,主要原因还是想多了,应该注意多观察一下题目性质:

题目要求求出这个式子的正整数解个数:

\(\frac{a}{x}+\frac{b}{c}=\frac{d}{y}\)

显然根据初中数学我们有:

\(x=\frac{acy}{dc-by}\)

所以显然 \(dc-by>0\)

而又因为 \(dc\le 10^6\),显然 \(y\le 10^6\),故枚举 \(y\) 然后 \(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=1e7+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');
}
/*
(ac+bx)/xc=d/y
ac+bx=dcx/y 
acy+bxy=dcx
考虑枚举x,则y=dcx/(ac+bx),显然需要保证(ac+bx)|dcx
考虑枚举y,则x=acy/(dc-by),(dc-by)|acy 
*/
signed main(){
//	freopen("equation.in","r",stdin); 
//	freopen("equation.out","w",stdout); 
	int T=read();
	while(T--){
		int a=read(),b=read(),c=read(),d=read();
		int sum=0,x=0;
		for(int y=1;(d*c-b*y)>0;y++){
			x=a*c*y/(d*c-b*y);
			if(a*c*y+b*x*y==d*c*x) sum++;
//			cout<<d*d*x<<" "<<a*c+b*x<<endl;
		}
		cout<<sum<<endl;
	}
	return 0;
}

T2

用时:约 \(20\) min

这是用时最少的一题,也是我认为本场最简单的一题,由于评测机性能不理想,以及我写的比较丑,被卡常卡到 \(70\)

观察到题目中的修改操作是一次改两个,对应于前缀异或数组的单点修改,所以直接用 map 或 unordered_map 维护前缀异或数组中某一个数的出现次数即可,复杂度为 \(O((n+q)\log n)\)\(O(n+q)\)

#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');
}
/*

先考虑静态怎么做,
很显然的套路,前缀转单点,01tire上插入查询可以做到nlogn

a[p]和a[p+1]都xor x,这样显然对于p+1~n的前缀xor无影响
只需要做一次单点修改,单点查询就好了
复杂度nlogn,期望得分100pts

其实只能得70,因为毒瘤出题人卡空间,加上动态开点也许就行了

突然感觉自己好naive,差点被骗了

直接拿个map维护,nlogn的时空复杂度完全没问题
 
*/
int n,a[MAX],s[MAX],q;
map<int,int> mp;
signed main(){
//	return system("fc 1.out xor2.ans"),0;
//	freopen("xor.in","r",stdin);
//	freopen("xor.out","w",stdout);
	n=read(),q=read();
	ll ans=0;
	for(int i=1;i<=n;i++){
		a[i]=read();
		s[i]=(s[i-1]^a[i]);
		ans+=mp[s[i]];
		mp[s[i]]++;
		if(!s[i]) ans++;
	}
	while(q--){
		int p=read(),x=read();
		mp[s[p]]--;ans-=mp[s[p]];
		if(!s[p]) ans--;
		s[p]^=x;ans+=mp[s[p]];
		mp[s[p]]++;
		if(!s[p]) ans++;
		write(ans);putchar('\n'); 
	}
	return 0;
}

T3

用时:约 \(1\) h。

这题连想带写用了约 \(30\) min,后来在T1思考无果之后又过来写对拍,还真让我拍出来了,得亏拍了,不然非挂没不可,原因修改操作没有在原数组上修改。

依然是同样的原因,常数问题挂了 \(30\) pts。

#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');
}
/*
考虑统计每一位1,0,?的前缀和
初始ans=1
某一位的sum1+sum?!=(r-l+1) ans=0
某一位的sum0+sum?!=(r-l+1) ans=0
某一位sum?=(r-l+1) ans*=2
树状数组维护 
*/
int m,q,n;
char s[100010][31],ss[31];
int c[3][31][100010];//0 1 ? 
inline void add(int x,int pos,int w,int k){
	for(int i=pos;i<=m;i+=(i&-i)) c[k][x][i]+=w;
	return ;
}
inline int ask(int l,int r,int x,int k){
	int ret=0;
	for(int i=r;i;i-=(i&-i)) ret+=c[k][x][i];
	for(int i=l-1;i;i-=(i&-i)) ret-=c[k][x][i];
	return ret;
}
signed main(){
//	return system("fc 1.out string2.ans"),0;
//	freopen("1.in","r",stdin);
//	freopen("std.out","w",stdout);
//	freopen("string.in","r",stdin);
//	freopen("string.out","w",stdout);
	n=read(),m=read(),q=read();
	for(int i=1;i<=m;i++) scanf("%s",s[i]+1);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if(s[j][i]=='0') add(i,j,1,0);
			else if(s[j][i]=='1') add(i,j,1,1);
		}
	int res=0;
	while(q--){
		int opt=read();
		if(opt){
			int x=read();
			scanf("%s",ss+1);
			for(int i=1;i<=n;i++){
				if(ss[i]=='0') add(i,x,1,0);
				else if(ss[i]=='1') add(i,x,1,1);
				if(s[x][i]=='0') add(i,x,-1,0);
				else if(s[x][i]=='1') add(i,x,-1,1);
				s[x][i]=ss[i];
			} 
		}
		else{
			int ans=1,l=read(),r=read();
			int sum[3]={0};
			for(int i=1;i<=n;i++){
				for(int j=0;j<=1;j++) sum[j]=ask(l,r,i,j);
				if(!sum[0]&&!sum[1]) ans<<=1;
				else if(sum[0]&&sum[1]){
					ans=0;break;
				}
			}
			res^=ans;
//			cout<<ans<<endl;
		}
	}
	cout<<res<<endl;
	return 0;
}
/*
0?1101??1?
11??1?0??1
10?1?00000
?00100?110
00?01?111?
111?????00
1??0?1?01?
10?1?01000
1?1???01??
01??111???
*/
/*

10 10 10
0?1101??1?
?01?011110
10?1?00000
?10??1?11?
00?01?111?
111?????00
1??0?1?01?
10?1?01000
1?1???01??
01??111???
1
4 ?00100?110
0
4 4
1
2 11??1?0??1
1
4 ?10??1?11?
0
4 4
1
3 11?0??0?1?
1
9 01?100?011
1
10 ?10?0??00?
0
4 10
1
6 1?10??010?


*/

T4

posted @ 2022-10-24 20:13  wapmhac  阅读(20)  评论(0编辑  收藏  举报