分析:注意异或以后可能会大于2e6,所以数组应该开到4e6。还有一种巧妙的解法就是用异或的性质,b^a^b=a,所以可以看出必然都是偶数对。

1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 #include "cmath" 6 #include "vector" 7 using namespace std; 8 const int maxn=5000; 9 const int maxm=4e6+10; 10 int x[maxn],y[maxn]; 11 int vis[maxm]; 12 int n; 13 //vector<int> res; 14 int main() 15 { 16 scanf("%d",&n); 17 //res.push_back(0); 18 for(int i=1;i<=n;i++){ 19 scanf("%d",&x[i]); 20 vis[x[i]]=1; 21 //res.push_back(x[i]); 22 } 23 for(int i=1;i<=n;i++){ 24 scanf("%d",&y[i]); 25 vis[y[i]]=1; 26 //res.push_back(y[i]); 27 } 28 int cnt=0; 29 for(int i=1;i<=n;i++){ 30 for(int j=1;j<=n;j++){ 31 int num=x[i]^y[j]; 32 if(vis[num]){ 33 cnt++; 34 //cout<<res[i]<<" "<<res[j]<<endl; 35 //cout<<num<<endl; 36 } 37 } 38 } 39 //cout<<(1^1)<<endl; 40 //cout<<cnt<<endl; 41 if(cnt%2==0) 42 cout<<"Karen"<<endl; 43 else 44 cout<<"Koyomi"<<endl; 45 }
分析:要求最后一位数分为几种情况,如果两数之差超过10的,因为最后一位出现0,所以必然为0。如果两数相等,直接对10曲余,否则直接暴力即可。

1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 #include "vector" 6 using namespace std; 7 long long a,b; 8 int main() 9 { 10 cin>>a>>b; 11 if(b-a>=10){ 12 cout<<"0"<<endl; 13 }else{ 14 long long t=b-a; 15 if(t==0) 16 cout<<"1"<<endl; 17 else if(t==1){ 18 cout<<b%10<<endl; 19 } 20 else{ 21 long long z=1; 22 vector<int>t; 23 for(long long i=a+1;i<=b;i++){ 24 int num=i%10; 25 t.push_back(num); 26 } 27 for(int i=0;i<t.size();i++) 28 z*=t[i]; 29 z=z%10; 30 cout<<z<<endl; 31 } 32 } 33 }
分析:题意比较难理解,就是给定三个集合,每个集合的元素个数分别为a,b,c。然后相同的一个集合当中任何两元素之间最短路必须大于等于3。求最多有多少种连线方式。根据题意我们就可以得知,首先同色的不可能相连,同时两个同色的不能连在一个其他颜色上。这个结论太重要了,这就说明了我们连任意两种颜色是独立的,于是最后结果就是(a,b),(a,c),(b,c)三者的乘积。而对于选取任意两种颜色,假设(a<b),那我们如果选取k条线段的话,必然有C(a,k)*C(b,k)*k!种组合方式,所以最终结果也就是k从0取到a的和,然后其余颜色也依次类推。

1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 #include "cmath" 6 #include "algorithm" 7 using namespace std; 8 typedef long long LL; 9 const LL mod= 998244353; 10 const int maxn=5050; 11 LL a[10]; 12 LL f[maxn],dp[maxn][maxn]; 13 void init(int n){ 14 f[0]=1; 15 for(int i=1;i<=n;i++){ 16 f[i]=f[i-1]*i; 17 f[i]%=mod; 18 } 19 for(int i=0;i<=n;i++){ 20 dp[i][0]=1; 21 } 22 for(int i=1;i<=n;i++){ 23 for(int j=1;j<=i;j++){ 24 dp[i][j]=(dp[i-1][j-1]%mod+(dp[i-1][j]%mod))%mod; 25 } 26 } 27 } 28 int main() 29 { 30 cin>>a[1]>>a[2]>>a[3]; 31 sort(a+1,a+4); 32 init(5000); 33 LL num1=0,num2=0,num3=0; 34 for(int i=0;i<=a[1];i++){ 35 num1+=((dp[a[1]][i]%mod*(dp[a[2]][i]%mod))%mod*f[i])%mod; 36 num1%=mod; 37 } 38 for(int i=0;i<=a[2];i++){ 39 num2+=((dp[a[2]][i]%mod*(dp[a[3]][i]%mod))%mod*f[i])%mod; 40 num2%=mod; 41 } 42 for(int i=0;i<=a[1];i++){ 43 num3+=((dp[a[1]][i]%mod*(dp[a[3]][i]%mod))%mod*f[i])%mod; 44 num3%=mod; 45 } 46 LL ans=((num1*num2)%mod*num3)%mod; 47 cout<<ans<<endl; 48 }
分析:围墙之间不相交,所以我们可以把每个围墙内部都设置成一个值,询问的时候只要看两个点的值是否相同即可。那么怎么
将一个围墙内设为一个值呢,我们可以利用二维BIT,利用前缀和,进行区间更新,单点查询,跟一维的时候区间更新单点更新一
样。那么删除的时候怎么快速得到这个围墙原来设置的是什么值呢,我们可以用哈希,将四个坐标哈希成一个值。

1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 using namespace std; 6 typedef long long LL; 7 const int maxn=2500+10; 8 const LL val=2333; 9 LL c[maxn][maxn]; 10 int n,m,q; 11 int lowbit(int x){ 12 return x&(-x); 13 } 14 void add(int x,int y,LL k){ 15 for(int i=x;i<=n;i+=lowbit(i)) 16 for(int j=y;j<=m;j+=lowbit(j)) 17 c[i][j]+=k; 18 } 19 void update(int x1,int y1,int x2,int y2,LL k){ 20 add(x2+1,y2+1,k); 21 add(x2+1,y1,-k); 22 add(x1,y2+1,-k); 23 add(x1,y1,k); 24 } 25 LL sum(int x,int y){ 26 LL ans=0; 27 for(int i=x;i;i-=lowbit(i)) 28 for(int j=y;j;j-=lowbit(j)) 29 ans+=c[i][j]; 30 return ans; 31 } 32 int main() 33 { 34 scanf("%d%d%d",&n,&m,&q); 35 for(int cas=1;cas<=q;cas++){ 36 int num,x1,y1,x2,y2; 37 scanf("%d%d%d%d%d",&num,&x1,&y1,&x2,&y2); 38 LL ans=x1; 39 ans=ans*val+y1; 40 ans=ans*val+x2; 41 ans=ans*val+y2; 42 if(num==1) 43 update(x1,y1,x2,y2,ans); 44 else if(num==2) 45 update(x1,y1,x2,y2,-ans); 46 else{ 47 LL ans1=sum(x1,y1); 48 LL ans2=sum(x2,y2); 49 if(ans1==ans2) 50 cout<<"Yes"<<endl; 51 else 52 cout<<"No"<<endl; 53 } 54 } 55 }