這真是一場神奇的比賽,比賽中各種猜想各種對,但我都無法證明,無語了,正式比賽中要能有這狀態那我不無敵了?不廢話了,上題解吧。
http://codeforces.com/contest/289/problem/A
A:水題吧,求出每個區間中所包含的數的個數,求和後,看和k的倍數差多少即可。
#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>#define maxn 100010using namespace std;int main(){ //freopen("dd.txt","r",stdin); int n,k,l,r,sum=0; scanf("%d%d",&n,&k); while(n--) { scanf("%d%d",&l,&r); sum+=r-l+1; } sum%=k; printf("%d\n",(k-sum)%k); return 0;}
http://codeforces.com/contest/289/problem/B
B:如果矩陣中有兩個數的差不是d的倍數則無解,否則,我們假設要把所有的數變成a[1][1],每個矩陣需要多少步,(這裡的步數是指增加的次數,如果要減少的話則為負數)比如說矩陣是
8 4
12 14
d為2.則a[1][1]需要0步,a[1][2]需要2步,a[2][1]需要-2步,a[2][2]需要-3步。
假設我們得到每個矩陣中的步數依次為b1 b2 b3.......bn*m,則我們及時要求一個j,使得|b1-bj|+|b2-bj|......+|bn*m-bj|最小,事實上bj是數列b的中位元時,得到的和最小(顯然吧。。。)。
#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>#define maxn 110using namespace std;int bo[maxn][maxn];int a[10010];int init(int n,int m,int d){ int i,j,num=1,tmp=bo[1][1]; a[1]=0; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(i==1&&j==1) continue; int tt=bo[i][j]-tmp; //printf("%d\n",tt); if(tt%d) return 0; tt/=d; a[++num]=tt; } } return 1;}int main(){ freopen("dd.txt","r",stdin); int n,m,d,num=0,i,j; scanf("%d%d%d",&n,&m,&d); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) scanf("%d",&bo[i][j]); } if(init(n,m,d)) { sort(a+1,a+n*m+1); int ans=0,tmp=a[(1+n*m)/2]; for(i=1;i<=n*m;i++) { ans+=abs(a[i]-tmp); } printf("%d\n",ans); } else printf("-1\n"); return 0;}
http://codeforces.com/contest/289/problem/C
C: 貪心即可,首先若k>n或者k==1且n>1時無解。k==n,我們依次輸出abcde.....即可,若k<n,則前n-k個字母一定是abababab...類型的串,我們在最後k個字元中構造滿足條件1的解,若第n-k個字元為b,則我最後k個字元為abcde...即可,否則,最後k個字元為bacde....即可。
#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>#define maxn 100010using namespace std;int main(){ //freopen("dd.txt","r",stdin); int n,k; scanf("%d%d",&n,&k); if(k==1) { if(n==1) printf("a\n"); else printf("-1\n"); } else if(k>n) printf("-1\n"); else if(k==n) { for(int i=1;i<=n;i++) printf("%c",'a'+i-1); printf("\n"); } else { int i; for(i=1;i<=n-k;i++) { if(i%2) printf("a"); else printf("b"); } if((n-k)%2) { printf("ba"); } else printf("ab"); for(i=1;i<=k-2;i++) printf("%c",'b'+i); printf("\n"); } return 0;}
http://codeforces.com/contest/289/problem/D
D:有公式,對於 n,k,答案為 (k^(k-1))*((n-k)^(n-k)) 注意這裡的^表示乘方運算。
什麼,你問我為什嗎?。。。。。。這是個謎。。。。。。
隨便YY的一個公式,竟然過了。。。其實我就是根據前兩個範例推的公式啊。。。傷不起。。。大牛勿噴啊。。。
#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>#define ll long long#define mod 1000000007using namespace std;ll pow[1010][2];void init(){ ll i,j; pow[0][0]=pow[0][1]=1; for(i=1;i<=1000;i++) { ll tmp=1; for(j=1;j<i;j++) { tmp=(tmp*i)%mod; } pow[i][0]=tmp; pow[i][1]=(tmp*i)%mod; }}int main(){ //freopen("dd.txt","r",stdin); ll n,k; init(); scanf("%I64d%I64d",&n,&k); printf("%I64d\n",(pow[n-k][1]*pow[k][0])%mod); return 0;}
http://codeforces.com/contest/289/problem/E
E:這道題再次證明了我YY的功力,實在沒頭緒,YY了一個貪心演算法,竟然又過了。。。神RP啊,昨天要是做比賽就好了。。。。
由於我沒辦法證明演算法的正確性,而且演算法也不是很好描述,所以先放在這裡,等到我能夠證明了的時候再來補。。。,如果有哪位大牛知道證明,歡迎來討論!!謝謝!!
#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#define ll long long#define maxn 1000010using namespace std;int getlen(int x){ int num=0; while(x) { num++; x/=2; } return num;}int vis[maxn];ll ans=0;int main(){ //freopen("dd.txt","r",stdin); int n; scanf("%d",&n); int len=getlen(n),i; int limit=(1<<len)-1; memset(vis,0,sizeof(vis)); for(i=n;i>=0;i--) { if(vis[i]) continue; int t=limit-i; for(int j=len;j>=1;j--) { if(t<=n&&!vis[t]) { ans+=(t^i); vis[i]=t; vis[t]=i; if(t!=i) ans+=(t^i); break; } if((1<<(j-1))&t) { t-=(1<<(j-1)); } } } printf("%I64d\n",ans); for(i=0;i<=n;i++) printf("%d ",vis[i]); printf("\n"); return 0;}