2017 Multi-University Training Contest 2
找出上下界直接判断
1 #include <bits/stdc++.h> 2 using namespace std; 3 char s1[100005]; 4 char s2[100005]; 5 int n,a,b,c,d; 6 int main(){ 7 int t; 8 scanf("%d",&t); 9 while(t--){ 10 a=0; 11 scanf("%d%d%d",&n,&c,&d); 12 scanf("%s%s",s1,s2); 13 for(int i=0;i<n;i++){ 14 if(s1[i]==s2[i]) a++; 15 } 16 b=n-a; 17 int L=max(0,c-b),R=0; 18 if(a>c) R=c+b; 19 else R=n-(c-a); 20 if(d>=L&&d<=R){ 21 printf("Not lying\n"); 22 } 23 else{ 24 printf("Lying\n"); 25 } 26 } 27 28 29 return 0; 30 }
记录一个后缀最大值,贪心使每一个数最大。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int mod=1e9+7; 4 int n; 5 int a[500005]; 6 int b[500005]; 7 int suf[500005]; 8 int main(){ 9 while(scanf("%d",&n)!=EOF){ 10 int ans=0; 11 memset(suf,0,sizeof(suf)); 12 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 13 for(int i=1;i<=n;i++) scanf("%d",&b[i]); 14 sort(b+1,b+1+n); 15 for(int i=n;i>=1;i--) suf[i]=max(suf[i+1],a[i]-i); 16 ans=a[n+1]=suf[b[1]]; 17 int now=a[n+1]-(n+1); 18 for(int i=n+2;i<=n*2;i++){ 19 a[i]=max(suf[b[i-n]],now); 20 ans+=a[i]; ans%=mod; 21 } 22 printf("%d\n",ans); 23 } 24 25 return 0; 26 }
性质一:数列交换相邻两个数,逆序对奇偶性改变。
性质二:以从左到右从上到下为顺序看作一个数列,不论如何改变最终逆序对奇偶性不变,因为空格总还是需要回到空格处,所以操作是会相互抵消。
性质三:最终一定可以得到除了右下角的2*2以外,全都满足位置要求。
求逆序对,判断奇偶。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 LL n,m,p; 5 int main(){ 6 LL t; 7 scanf("%lld",&t); 8 while(t--){ 9 scanf("%lld%lld%lld",&n,&m,&p); 10 LL ans=0,tot=n*m-1; 11 while(tot>p){ 12 LL tmp=(tot+p-1)/p; 13 LL last=(tmp-1)*(p-1); 14 ans+=last*tmp/2; 15 tot-=tmp; 16 } 17 if(ans%2==0) printf("YES\n"); 18 else printf("NO\n"); 19 } 20 21 return 0; 22 }
f[1][n]的通项可以求出,再向后计算可得f[m][1]的公式。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const LL mod=1e9+7; 5 LL pow_mod(LL a,LL n){ 6 LL res=1,t=a; 7 while(n){ 8 if(n&1) res=(res*t)%mod; 9 t=(t*t)%mod; 10 n/=2; 11 } 12 return res; 13 } 14 LL inv(LL x){ 15 return pow_mod(x,mod-2); 16 } 17 LL n,m; 18 int main(){ 19 LL t; 20 cin>>t; 21 while(t--){ 22 cin>>n>>m; 23 LL ans1=pow_mod(2,m)*pow_mod( (pow_mod(2,n)-1+mod)%mod,m-1 )%mod; 24 LL ans2=pow_mod(-1,m)*pow_mod( (pow_mod(-1,n)-1+mod)%mod,m-1 )%mod; 25 LL ans=(ans1-ans2+mod)%mod; 26 ans=ans*inv((3*pow_mod(2,m-1))%mod)%mod; 27 cout<<ans<<endl; 28 } 29 30 return 0; 31 }
1007 If the starlight never fade
1.原根:假设一个数g是P的原根,那么g^i mod P的结果两两不同,且有 1<g<P, 0<i<P,归根到底就是g^(P-1) = 1 (mod P)当且仅当指数为P-1的时候成立.(这里P是素数)。
2.所有的数在取模的情况下都可以由原根的幂次表示,当模为1时,幂次为 p-1。
3.若 gcd(n,i)=1 则 gcd(n,n-i)=1。
4.由3可推出:[1,n]中与n互质的数的和为 phi(n)*n/2。
官方题解推导(对于每一个y,x的取值个数相同):
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const LL mod=1e9+7; 5 LL euler(LL n){ 6 LL ans=n; 7 for(LL i=2;i*i<=n;i++){ 8 if(n%i==0){ 9 ans-=ans/i; 10 while(n%i==0) n/=i; 11 } 12 } 13 if(n>1) ans-=ans/n; 14 return ans; 15 } 16 LL m,p,tmp; 17 void add(LL &x,LL y){ 18 x%=mod; y%=mod; 19 x=(x+y)%mod; 20 if(x<0) x+=mod; 21 } 22 LL fun(LL x){ 23 if(x==1) return 1; 24 else return (x*euler(x)/2)%mod; 25 } 26 int main(){ 27 LL t; 28 scanf("%lld",&t); 29 LL T=t; 30 while(t--){ 31 scanf("%lld%lld",&m,&p); 32 LL ans=0; 33 add(ans,-(p*(p-1)/2%mod)); 34 for(int i=1;i*i<=p-1;i++){ 35 if((p-1)%i==0){ 36 tmp=i; 37 add(ans,(tmp*tmp%mod)*fun((p-1)/tmp)); 38 if(i*i!=p-1){ 39 tmp=(p-1)/i; 40 add(ans,(tmp*tmp%mod)*fun((p-1)/tmp)); 41 } 42 } 43 } 44 printf("Case #%lld: %lld\n",T-t,ans*m%mod); 45 } 46 47 return 0; 48 }
每个数分开计算期望再求和。
总数小于13的容斥,大于13的枚举不存在的情况。
(13=log1e4)使得时间复杂度最小。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 LL n,m; 5 LL a[105][105]; 6 vector<LL> pp[10005][105]; 7 vector<LL> num; 8 struct node{ 9 LL x,y; 10 }; 11 vector<node> poLL[10005]; 12 LL solve(LL u){ 13 LL res=0; 14 for(LL i=1;i<=n;i++) 15 for(LL j=1;j<=m;j++){ 16 if(a[i][j]==u) continue; 17 LL ry=m+1; 18 for(int k=i;k<=n;k++){ 19 for(int q=0;q<pp[u][k].size();q++){ 20 if(pp[u][k][q]>=j) { 21 ry=min(ry,pp[u][k][q]); 22 break; 23 } 24 } 25 res+=ry-j; 26 } 27 } 28 return res; 29 } 30 LL vis[20]; 31 void dfs(LL deep,LL u,LL times,LL &res){ 32 if(deep>=poLL[u].size()){ 33 if(times==0) return; 34 LL lx=105,ly=105,rx=0,ry=0; 35 for(LL i=0;i<poLL[u].size();i++){ 36 if(vis[i]){ 37 lx=min(lx,poLL[u][i].x); 38 ly=min(ly,poLL[u][i].y); 39 rx=max(rx,poLL[u][i].x); 40 ry=max(ry,poLL[u][i].y); 41 } 42 } 43 if(times%2==1) res+=(n-rx+1)*lx*(m-ry+1)*ly; 44 else res-=(n-rx+1)*lx*(m-ry+1)*ly; 45 } 46 else{ 47 vis[deep]=1; 48 dfs(deep+1,u,times+1,res); 49 vis[deep]=0; 50 dfs(deep+1,u,times,res); 51 } 52 } 53 int main(){ 54 LL t; 55 scanf("%lld",&t); 56 while(t--){ 57 num.clear(); 58 scanf("%lld%lld",&n,&m); 59 for(LL i=0;i<=n*m;i++){ 60 poLL[i].clear(); 61 for(int j=1;j<=n;j++) pp[i][j].clear(); 62 } 63 for(LL i=1;i<=n;i++) 64 for(LL j=1;j<=m;j++){ 65 scanf("%lld",&a[i][j]); 66 num.push_back(a[i][j]); 67 poLL[a[i][j]].push_back((node){i,j}); 68 pp[a[i][j]][i].push_back(j); 69 } 70 sort(num.begin(),num.end()); 71 num.erase(unique(num.begin(),num.end()),num.end()); 72 LL ans=0; 73 LL tot=(n*(n+1)/2)*(m*(m+1)/2); 74 for(LL i=0;i<num.size();i++){ 75 LL v=num[i]; 76 if(poLL[v].size()<=13){ 77 memset(vis,0,sizeof(vis)); 78 LL tmp=0; 79 dfs(0,v,0,tmp); 80 ans+=tmp; 81 } 82 else ans+=tot-solve(v); 83 } 84 printf("%.9lf\n",(double)ans/tot); 85 } 86 return 0; 87 }
每一个区间gcd不为1,只要[1,n]的gcd不为1就好。
记录每一个数出现的次数维护前缀和,求出当gcd为每个数的倍数时的总数。
最后需要去重。
(题解给的是莫比乌斯变换)
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const LL mod=1e9+7; 5 LL n; 6 LL a[100005]; 7 LL x[100005]; 8 LL sum[100005]; 9 LL num[100005]; 10 LL pow_mod(LL a,LL n){ 11 LL res=1,t=a; 12 while(n){ 13 if(n&1) res=(res*t)%mod; 14 t=(t*t)%mod; 15 n/=2; 16 } 17 return res; 18 } 19 LL solve(LL x,LL min_num){ 20 LL res=1; 21 LL tmp=min_num/x; 22 while(tmp--){ 23 LL num=sum[min(x*(tmp+2)-1,100001LL)]-sum[min(x*(tmp+1)-1,100000LL)]; 24 if(num==0) continue; 25 res=(res*pow_mod(tmp+1,num))%mod; 26 } 27 return res; 28 } 29 int main(){ 30 LL t; 31 scanf("%lld",&t); 32 LL T=t; 33 while(t--){ 34 memset(num,0,sizeof(num)); 35 memset(sum,0,sizeof(sum)); 36 memset(x,0,sizeof(x)); 37 scanf("%lld",&n); 38 LL L=100005,R=0; 39 for(LL i=1;i<=n;i++){ 40 scanf("%lld",&a[i]); num[a[i]]++; 41 L=min(L,a[i]); R=max(R,a[i]); 42 } 43 for(LL i=1;i<=100003;i++) sum[i]=sum[i-1]+num[i]; 44 for(LL i=2;i<=L;i++) x[i]=solve(i,R); 45 for(LL i=L;i>=2;i--){ 46 for(LL j=i+i;j<=L;j+=i){ 47 x[i]=(x[i]-x[j]+mod)%mod; 48 } 49 } 50 LL ans=0; 51 for(int i=1;i<=L;i++) ans=(ans+x[i])%mod; 52 53 printf("Case #%lld: %lld\n",T-t,ans); 54 } 55 56 return 0; 57 }
整点中只存在正四边形。
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n; 4 int x[2005],y[2005]; 5 int vis[2005][2005]; 6 int main(){ 7 while(~scanf("%d",&n)){ 8 memset(vis,0,sizeof(vis)); 9 for(int i=1;i<=n;i++){ 10 scanf("%d%d",&x[i],&y[i]); 11 x[i]+=500; y[i]+=500; 12 vis[x[i]][y[i]]=1; 13 } 14 int ans=0; 15 for(int i=1;i<=n;i++){ 16 for(int j=i+1;j<=n;j++){ 17 int dx=x[i]-x[j]; 18 int dy=y[i]-y[j]; 19 if(vis[x[i]+dy][y[i]-dx]&&vis[x[j]+dy][y[j]-dx]) ans++; 20 if(vis[x[i]-dy][y[i]+dx]&&vis[x[j]-dy][y[j]+dx]) ans++; 21 } 22 } 23 printf("%d\n",ans/4); 24 } 25 26 return 0; 27 }