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?
*/