華東交通大學2013年ACM“雙基”程序設計競賽 最終排名:http://acm.hdu.edu.cn/diy/contest_ranklist.php?cid=20955&page=1
華東交通大學2013年ACM“雙基”程序設計競賽賽後重掛(對題目感興趣的同學可以去該網址重新提交代碼進行測試):http://acm.hdu.edu.cn/diy/contest_show.php?cid=21280
神犇的悲慘一生
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 432 Accepted Submission(s) : 243
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
XX神犇的一生,幼年佔了1/6,又過了1/12的青春期,又談了1/6的戀愛後結婚,m年後生了個孩子,名叫神牛,神牛比神犇先死n年,神牛的壽命是神犇的一半
現在人們邀請作爲下一任神犇的你,算出這位神犇活了多少歲。。(神犇的命都是好長的)
注意
請採用下面這種格式輸入
#include<cstdio>
using namespace std;
int main()
{
int n , m;
while(scanf("%d%d",&n,&m) != EOF)
{
}
return 0;
}
Input
Output
Sample Input
50 70
Sample Output
1440
Author
#include<cstdio>
using namespace std;
int main()
{
int n , m;
while(scanf("%d%d",&n,&m) != EOF)
{
printf("%d\n",12 * (n + m));
}
return 0;
}
Go shopping
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 622 Accepted Submission(s) : 35
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
趕巧交大旁邊有一家商場新店開張,正在進行打折促銷活動。於是,咱們所有隊員都在商場中大肆購買之後,在收銀臺前排起了長隊。
話說回來,這家商場的打折方式有些奇怪:他們從在收銀臺前付賬的所有n位顧客中,每隔m名顧客便挑選一位顧客享受七五折優惠,其餘顧客只能享受九五折。
爲了方便付賬,Awell拜託老闆將付賬者的姓名和付款金額打印出來,作爲參考。
你需要注意的是,在收銀臺前長長的隊伍中,有的可不止是ACM隊員,同樣,還有很多交大的同學慕名前來消費。爲了區分他們,我們規定,所有ACM隊員必須在姓名前加上前綴“ACM”(不包含雙引號,且不存在非ACM隊員的同學名字前面出現ACM字樣)。
現在,請機智的你爲Awell編寫一個小程序,算一算他總共需要花費多少錢呢?
Input
你可以通過
while(scanf(......)!=EOF)
{
……;
}
的形式進行輸入。接下來有n行,每行將會輸入消費者的姓名(長度不超過20個字符),以及他們各自消費的金額(以“元”位單位,最高可能精確到小數點後兩位)。
Output
Sample Input
4 2 Newee 123.12 ACMAwell 100 PRO 345.5 Sirius 456.99 5 2 Newee 123.12 ACMAwell 100 PROPHET 345.5 Sirius 456.99 ACMProphetK 100
Sample Output
75.0 170.0
Author
#include<stdio.h>
int main()
{
int n,m,i;
double sum,buy;
char name[25];
while(scanf("%d%d",&n,&m)!=EOF)
{
sum=0;
for(i=1;i<=n;i++)
{
scanf("%s%lf",name,&buy);
if(name[0]=='A'&&name[1]=='C'&&name[2]=='M')
{
if(i%m==0)
sum+=buy*0.75;
else
sum+=buy*0.95;
}
}
printf("%.1f\n",sum+0.0499);
}
return 0;
}
中秋掛燈籠
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 44 Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
現在中秋節到了,鄉里需要派一個人掛n個燈籠到這個樹上(燈籠只能掛到樹的節點上),由於風俗原因,當樹上的一個節點掛了燈籠後,由這個節點開始產生的所有的分支都不準掛燈籠,已知每個燈籠都有一個重量W
而每個燈籠掛到樹上所消耗的體力是樹的根節點(地面)到燈籠的位置之間的距離L*W(兩節點之間距離爲1)
由於這個人體力有限,所以希望花費的體力最少,你能幫他算算他花費的最少體力是多少嗎?
Input
每行首先有個n(0<=n<=10000)表示燈籠的數量,接下來一行每行有n個數表示燈籠的重量W(0<=W<=10000)
輸入以文件末尾結束
Output
Sample Input
4 1 1 2 1 1 1
Sample Output
15 1
Author
/*分析:
由於題目說:1.當樹上的一個節點掛了燈籠後,由這個節點開始產生的所有的分支都不準掛燈籠
2.並且掛燈籠花費的力氣是L*W,即到根的長度*權值
需要求掛完全部燈籠花費的最小力氣,這就是完完全全的Huffman Tree模型
所以只要照着Huffman Tree建立樹求最小值即可
*/
//第二種寫法:用優先隊列
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<algorithm>
#include<map>
#include<iomanip>
#define INF 99999999
using namespace std;
const int MAX=10000+10;
int father[MAX*2],dp[MAX*2],s[MAX];
struct Node{
int id,val;
bool operator<(const Node &a)const{
return val>a.val;
}
}p,a,b;
void Init(int num){
for(int i=0;i<2*num;++i){
father[i]=i;
dp[i]=0;
}
}
int findset(int i){
if(dp[i] || father[i] == i)return dp[i];
return dp[i]=findset(father[i])+1;
}
int main(){
int n;
while(~scanf("%d",&n)){
priority_queue<Node>q;
Init(n);
for(int i=0;i<n;++i){
scanf("%d",&s[i]);
p.val=s[i],p.id=i;
q.push(p);
}
for(int i=0;i<n-1;++i){//做n-1次合併操作即可
a=q.top(),q.pop();
b=q.top(),q.pop();
father[a.id]=father[b.id]=p.id=n+i;
p.val=a.val+b.val;
q.push(p);
}
__int64 sum=0;
for(int i=0;i<n;++i){
sum+=s[i]*(findset(i)+1);
}
printf("%I64d\n",sum);
}
return 0;
}
求和
Time Limit : 9000/3000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 47 Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
f[n]=(1^x) * (x^1) + (2^x) * (x^2) + (3^x) * (x^3) + (4^x) * (x^4) + (5^x) * (x^5) +...+ (n^x) * (x^n)
定義另一個關係:
g[n]=k*n+b
現在給定x,k,n,b的值,求f[g[0]] + f[g[1]] + f[g[2]] + f[g[3]] + ...+ f[g[n-2]] + f[g[n-1]] + f[g[n]]
輸出對20130919取模後的值
Input
其中0<x<=20,k,,n,b是不超過 1,000,000,000正整數
輸入以文件末尾結束
Output
Sample Input
1 1 1 1 2 2 2 2
Sample Output
4 3814
Author
/*分析:
假定f[n]=A^n;//A爲矩陣,f[n]爲A^n的某項值
則sum(f[g[n]])=f[g[0]]+f[g[1]]+...+f[g[n]]
=A^b+A^(k+b)+A^(2k+b)+A^(3k+b)+...+A^(nk+b)
=A^b+A^b(A^k+A^2k+A^3k+A^4k+...+A^nk)
將A^k看成一個新的矩陣B,則原式:
=A^b+A^b(B^1+B^2+B^3+...+B^n);//A^b,A^k用矩陣快速冪求出,括號中的用二分矩陣可求
所謂二分矩陣:A^1+A^2+A^3+A^4+A^5+A^6=(A^1+A^2+A^3)+A^3(A^1+A^2+A^3)
現在問題的關鍵轉化爲如何求矩陣A:
fn=1^x * x^1 + 2^x * x^2 +...+ n^x * x^n;
fn+1=1^x * x^1 + 2^x * x^2 +...+ n^x * x^n+(n+1)^x * x^(n+1)=fn+(n+1)^x * x^(n+1),將(n+1)^x二項式展開然後用矩陣快速冪
構造矩陣:
|1 xC(x,0) xC(x,1) xC(x,2) ... xC(x,x)| |fn | |f(n+1) |
|0 xC(0,0) 0 0 ... 0 | |x^n * n^0| |x^(n+1) * (n+1)^0|
|0 xC(1,0) xC(1,1) 0 ... 0 | *|x^n * n^1|=|x^(n+1) * (n+1)^1|
|0 xC(2,0) xC(2,1) xC(2,2) ... 0 | |x^n * n^2| |x^(n+1) * (n+1)^2|
|... | |... | |... |
|0 xC(x,0) xC(x,1) xC(x,2) ... xC(x,x)| |x^n * n^x| |x^(n+1) * (n+1)^x|
*/
//第一種方法,採用二分求A^1+A^2+A^3...+A^n
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<iomanip>
#define INF 99999999
typedef __int64 LL;
using namespace std;
const int MAX=20+10;
const int mod=20130919;
LL array[MAX][MAX],ans[MAX][MAX];
LL temp[MAX][MAX],sum[MAX][MAX];
int n,x,k,b;
LL C(int n,int m){
if(m<0 || m>n)return 0;
LL num=1;
for(int i=1;i<=m;++i){
num=num*(n-m+i)/i;
}
return num%mod;
}
void MatrixInit(LL a[MAX][MAX],LL b[MAX][MAX],int flag){
a[0][0]=1;
if(flag == 2)a[0][0]=b[0][0];
//計算第一行,總共有x+2行,x+2列
for(int j=1;j<=x+1;++j){//C(x,0)~C(x,x)所以是x+1列
if(flag == 1)a[0][j]=x*C(x,j-1)%mod;//初始化矩陣A
else if(flag == 0)a[0][j]=0;//初始化單位矩陣
else a[0][j]=b[0][j];//a=b
}
//計算第二行到第x+2行
for(int i=1;i<=x+1;++i){
for(int j=0;j<=x+1;++j){
if(flag == 1)a[i][j]=x*C(i-1,j-1)%mod;//初始化矩陣A
else if(flag == 0)a[i][j]=(i == j);//初始化單位矩陣
else a[i][j]=b[i][j];//a=b
}
}
}
void MatrixAdd(LL a[MAX][MAX],LL b[MAX][MAX]){
for(int i=0;i<=x+1;++i){
for(int j=0;j<=x+1;++j){
a[i][j]=(a[i][j]+b[i][j])%mod;
}
}
}
void MatrixMult(LL a[MAX][MAX],LL b[MAX][MAX]){
LL c[MAX][MAX]={0};
for(int i=0;i<=x+1;++i){
for(int j=0;j<=x+1;++j){
for(int k=0;k<=x+1;++k){
c[i][j]+=a[i][k]*b[k][j];
}
}
}
for(int i=0;i<=x+1;++i){
for(int j=0;j<=x+1;++j)a[i][j]=c[i][j]%mod;
}
}
void MatrixPow(int k){
MatrixInit(sum,sum,0);//sum=1
MatrixInit(temp,array,2);//temp=array
while(k){
if(k&1)MatrixMult(sum,temp);
MatrixMult(temp,temp);
k>>=1;
}
}
void MatrixSum(int k){//A^1+A^2+...+A^k=(A^1+A^2+...A^k/2)+A^m(A^1+A^2+...+A^k/2)=(1+A^m)*(A^1+A^2+...A^k/2)
if(k == 1){MatrixInit(ans,array,2);return;}//ans=A,這裏的A事上面分析的B
MatrixSum(k/2);//A^1+A^2+...+A^k/2
MatrixPow(k+1>>1);//A^m,m=(k+1)/2
//k爲偶數則(1+A^m)*(A+A^2+A^3...),m=(k+1)/2
MatrixInit(temp,temp,0);//temp=1
MatrixAdd(temp,sum);//temp=1+A^m
MatrixMult(ans,temp);//ans=ans*temp
//k爲奇數則A^m+(1+A^m)*(A+A^2+A^3...),m=(k+1)/2
if(k&1)MatrixAdd(ans,sum);//ans=A^m+ans,奇數的話A^1+A^2+...+A^k=(A^1+A^2+...A^k/2)+A^m+A^m(A^1+A^2+...+A^k/2)
}
int main(){
while(~scanf("%d%d%d%d",&x,&k,&n,&b)){
MatrixInit(array,array,1);//初始化array=A
MatrixPow(k);//求sum=A^k
MatrixInit(array,sum,2);//array=A^k=B
MatrixSum(n);//求ans=B^1+B^2+...+B^n
MatrixInit(array,array,1);//初始化array=A
MatrixPow(b);//求sum=A^b
MatrixMult(ans,sum);//ans=ans*sum=ans*A^b
MatrixAdd(ans,sum);//ans=ans+A^b
printf("%I64d\n",ans[0][1]);
}
return 0;
}
too_weak的奶酪
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 103 Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Input
每組數據以兩個整數N,K。N代表棋盤的規模是N x N,K代表老鼠的數目。
接下來有K行,每行兩個數x,y。分別代表每隻老鼠的座標(下標從1開始)
1. 1 <= N<= 10^9,1<=k<=10^6
2. 1<=x,y<=10^9
Output
Sample Input
4 4 1 2 2 1 2 3 3 2
Sample Output
11
Author
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1000005;
int x[maxn],y[maxn];
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
for(int i=0;i<k;++i)
scanf("%d%d",&x[i],&y[i]);
int numx=1,numy=1;
sort(x,x+k);
for(int i=1;i<k;++i)
if(x[i]!=x[i-1]) ++numx;
sort(y,y+k);
for(int i=1;i<k;++i)
if(y[i]!=y[i-1]) ++numy;
printf("%I64d\n",1ll*n*(numy+numx)-1ll*numy*numx-k);
}
return 0;
}
Lentty要喫巧克力
Time Limit : 6000/2000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 57 Accepted Submission(s) : 5
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Input
每組數據以四個整數N,M。N代表初始的巧克力數目,M代表操作數。
第一行給定n,第二行含有n個正整數,代表每塊巧克力的美味值wi。
每塊巧克力的下標從0-n-1.。
操作分4種,Query x y 代表查詢某一個區間內的美味最大值。
Ask x 代表查詢某一塊巧克力的美味值。
Change x y 代表將第x塊的美味值變成y
Add x y 代表講從第x塊到第y塊巧克力的美味值分別增加1.
1. 1 <= N<= 100000
2.1<= M <= 100000
2. Wi <= 5000
Output
對於每一個Ask 輸出一個整數,代表這塊巧克力的美味值。
Sample Input
10 4 1 2 3 4 5 6 7 8 9 10 Ask 0 Change 0 1 Add 0 2 Query 0 2
Sample Output
1 4
Author
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
const int maxn=100005;
int a[maxn];
int maxx[4*maxn], flag[4*maxn];
void push_down(int u, int l, int r)
{
if(flag[u])
{
flag[2*u]+=flag[u];
flag[2*u+1]+=flag[u];
maxx[2*u]+=flag[u];
maxx[2*u+1]+=flag[u];
flag[u]=0;
}
}
void build(int u, int l, int r)
{
flag[u]=0;
if(l==r)
{
maxx[u]=a[l];
return ;
}
int mid=(l+r)>>1;
build(lz);
build(rz);
maxx[u]=max(maxx[2*u],maxx[2*u+1]);
}
void Update(int u, int l, int r, int tl, int tr, int c, int op)
{
if(tl<=l&&r<=tr)
{
if(op==1)
{
flag[u]+=c;
maxx[u]+=c;
}
else
{
maxx[u]=c;
}
return ;
}
push_down(u,l,r);
int mid=(l+r)>>1;
if(tr<=mid) Update(lz,tl,tr,c,op);
else if(tl>mid) Update(rz,tl,tr,c,op);
else
{
Update(lz,tl,mid,c,op);
Update(rz,mid+1,tr,c,op);
}
maxx[u]=max(maxx[2*u],maxx[2*u+1]);
}
int Query(int u, int l, int r, int tl, int tr)
{
if(tl<=l&&r<=tr) return maxx[u];
push_down(u,l,r);
int mid=(l+r)>>1;
if(tr<=mid) return Query(lz,tl,tr);
else if(tl>mid) return Query(rz,tl,tr);
else
{
int t1=Query(lz,tl,mid);
int t2=Query(rz,mid+1,tr);
return max(t1,t2);
}
}
int main()
{
int n, m;
while(cin >> n >> m)
{
for(int i=1; i<=n; i++) scanf("%d",a+i);
build(1,1,n);
for(int i=1; i<=m; i++)
{
char ch[10];
int x, y;
scanf("%s",ch);
if(strcmp(ch,"Add")==0)
{
scanf("%d%d",&x,&y);
x++, y++;
Update(1,1,n,x,y,1,1);
}
else if(strcmp(ch,"Change")==0)
{
scanf("%d%d",&x,&y);
x++;
Update(1,1,n,x,x,y,2);
}
else if(strcmp(ch,"Ask")==0)
{
scanf("%d",&x);
x++;
printf("%d\n",Query(1,1,n,x,x));
}
else
{
scanf("%d%d",&x,&y);
x++,y++;
printf("%d\n",Query(1,1,n,x,y));
}
}
}
return 0;
}
拯救之路
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 14 Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Note:爲了讓拯救行動更加容易,應該讓拯救路線儘量短,同時應該讓“FUCK”序列儘量長。
Input
每組測試數據有兩個整數n(1<=n<=1500),m(1<=m<=20000),表示n個忍者根據地和m條道路。
接下來輸入m行,每行有4個變量 “u v L c”,表示這是一條路介於根據地u,v(1<=u,v<=n),這條路的長度是L(1<=L<=1000000),c是一個標記字符(‘F’,‘U’,‘C’,‘K’中的一種)。
Output
Sample Input
2 4 4 1 2 1 F 2 1 1 U 1 3 1 C 3 4 1 K 4 4 1 2 1 F 2 3 1 U 3 4 1 C 4 1 1 K
Sample Output
4 1 Impossible
Author
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long lld;
const int mn=3333;
const int mm=44444;
const lld oo=1e15;
int reach[mm], next[mm], flow[mm], ch[mm];
lld head[mn], que[mn], dis[mn][4], cnt[mn][4], inque[mn];
int n, edge;
void addedge(int u, int v, int c1, int c2, char c)
{
ch[edge]=c, reach[edge]=v, flow[edge]=c1, next[edge]=head[u], head[u]=edge++;
ch[edge]=c, reach[edge]=u, flow[edge]=c2, next[edge]=head[v], head[v]=edge++;
}
int find(char c)
{
if(c=='F') return 0;
else if(c=='U') return 1;
else if(c=='C') return 2;
else return 3;
}
bool spfa()
{
int l=0, h=0;
memset(inque,0,sizeof(inque));
for(int i=1; i<=n; i++)
for(int j=0; j<4; j++) dis[i][j]=oo, cnt[i][j]=0;
inque[1]=1;
dis[1][0]=0;
que[l++]=1;
while(l!=h)
{
int u=que[h++];
if(h==mn) h=0;
inque[u]=0;
for(int i=head[u]; i>=0; i=next[i])
{
int s=find(ch[i]), v=reach[i], val=flow[i];
if(dis[v][(s+1)%4]>=dis[u][s]+val)
{
if(dis[v][(s+1)%4]==dis[u][s]+val)
{
if(cnt[u][s]+1>cnt[v][(s+1)%4]) cnt[v][(s+1)%4]=cnt[u][s]+1;
else continue;
}
else
{
dis[v][(s+1)%4]=dis[u][s]+val;
cnt[v][(s+1)%4]=cnt[u][s]+1;
}
if(!inque[v])
{
inque[v]=1;
que[l++]=v;
if(l==mn) l=0;
}
}
}
}
if(dis[n][0]==oo||!cnt[n][0]) return false;
else return true;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int m, T, tcase=0;
cin >> T;
while(T--)
{
cin >> n >> m;
edge=0;
memset(head,-1,sizeof(head));
int mp[4]={0,0,0,0}, ct=0;
while(m--)
{
int u, v, val, se;
char sh[3];
scanf("%d%d%d%s",&u,&v,&val,sh);
addedge(u,v,val,val,sh[0]);
if(n==1&&u==1&&v==1)
{
se=find(sh[0]);
if(!mp[se]) ct++, mp[se]=val;
else mp[se]=min(mp[se],val);
}
}
if(ct==4)
{
lld sum=mp[0]+mp[1]+mp[2]+mp[3];
printf("%I64d %d\n",sum,ct/4);
continue;
}
bool ok=spfa();
if(!ok) puts("Impossible");
else printf("%I64d %I64d\n",dis[n][0],cnt[n][0]/4);
}
return 0;
}
ZEROm的乘法運算
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 24 Accepted Submission(s) : 1
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
int Sum=0;
for(int i=1;i<=N;i++)
for(int j=i+1;j<=N;j++)
for(int k=j+1;k<=N;k++)
Sum+=a[i]*a[j]*a[k];
Input
每組數據的第一行包含一個正整數N(1 <= N<= 1000000),說明第二行有N個數。
第二行有N個數,分別代表a[1],a[2],a[3]....a[N].(0<=a[i]<=10^9)
Output
Sample Input
5 1 2 3 4 5
Sample Output
225
Author
#include <cstdio>
using namespace std;
typedef long long LL;
const int mod = 9973;
const int maxn =1000000+5;
LL a[maxn];
int main()
{
int n;
while(~scanf("%d",&n)){
LL sum=0,xxx=0;
for(int i=0;i<n;i++){
scanf("%I64d",&a[i]);
sum=(sum+a[i])%mod;
xxx=xxx+a[i]*a[i]%mod*a[i]%mod;
}
for(int i=0;i<n;i++)
xxx=(xxx+3*a[i]*a[i]%mod*(sum-a[i])%mod)%mod;
sum=sum*sum%mod*sum%mod;
sum=((sum-xxx)%mod+mod)%mod;
printf("%I64d\n",sum*8311%mod);
}
return 0;
}