得分情况:
估分:
30(T1)+100(T2)+0(T3)=130;
实际:
30(T1)+60(T2)+10(T3)=100; QAQ
是我高看自己了
T1 友好数对:
题意:
如果一个数a能由一个数b旋转得到,那么我们称为友好数对,如12345和45123为友好数对,12345和54321不为友好数对。给出两个正整数L,R,求有多少友好数对,满足L<=a (说实话没看懂后面这什么玩意)
输入格式:
第一行一个整数T,表示数据组数,每组数据两个正整数L,R。
输出格式:
对于每组数据,输出一个整数表示答案。
样例输入:
4 1 9 10 40 100 500 1111 2222
样例输出:
0 3 156 287
数据范围:
对于30%的数据满足L,R<=1000
对于100%的数据满足L,R<=2000000,T<=30,L,R位数相同。
大概理解为: 一个数a 把a分为两段 两段长度不能为零 然后把这两段交换位置得到b 要求L<=a,b<=R且a!=b 然后求有多少对这样的数
列如 : a=12345,把a分成123、45两段 , 然后交换得45、123 , 粘起来就成了b=45123;
分析:
看一下数据范围 L,R<=2*1e6,T<=30;
大概算一下2*1e6*30=6*1e7 暴力枚举完全搞得定
因为一个数可能旋转成同一个数多次(比如 232323 )所以要判一下重
只需要把每个数的旋转方式都来一遍 ,再判一下重,就搞定了 (没判重所以来了三十分)
上代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 6 using namespace std; 7 8 bool st[2000002];//判重用的 9 10 int main() 11 { 12 13 int T; 14 scanf("%d",&T); 15 while(T--) 16 { 17 int a,b,res=0,t[10],rec[10]; 18 19 memset(st,false,sizeof(st)); 20 21 scanf("%d%d",&a,&b); 22 23 for(int i=a;i<=b;i++) 24 { 25 26 int cnt=1,l=a,p=0; 27 28 while(l)//看一下有多少位 下面分段用 29 { 30 l/=10; 31 cnt*=10; 32 } 33 34 for(int j=10;j<cnt;j*=10)//枚举从哪一位分段 35 { 36 37 int k=i%j*(cnt/j)+i/j; 38 39 if(k>=a&&k<i) 40 { 41 if(st[k]) continue;//已经有了就不加了 42 rec[p++]=k; 43 st[k]=true; 44 res++; 45 } 46 } 47 48 for(int j=0;j<p;j++) st[rec[j]]=false;//把刚刚判的重弄回去 49 } 50 51 printf("%d\n",res); 52 } 53 }
搞定
T2 路径数:
题意:
Euphemia到一个N*N的药草田里采药,她从左上角的格子田(第一行,第一列)出发,要到达右下角(第N行,第N列)的格子田,每次她可以走到与当前格子有边相邻的格子去,但她不会走已经走过的格子,而且出于对美的要求,她走过的路径是关 于 左下-右上 对角线对称的。由于地势不同,在每个格子田采药都会有一个疲劳度Tij,Euphemia想知道:有多少条合法路径,可以使得她采药的疲劳度最小。
输入格式:
多组数据。
每组数据第一行一个整数N,接下来N行,每行N个非零数字(1,2,3...9中一个),表示格子田的疲劳度。
当N=0,输入结束。
输出格式:
对于每组数据,输出一个整数表示答案,答案%1000000009。
样例输入:
2 1 1 1 1 3 1 1 1 1 1 1 2 1 1 0
样例输出:
2 3
数据范围:
对于20%的数据满足N<=5。
对于另外20%的数据满足N<=40。
对于100%的数据满足N<=100,不超过50组数据。
大概理解为: 从左上角走到右下角的最短路径方案数,但题目有个路径关于 左下-右上 对角线对称,大概理解为这样
我画的好丑
分析:
这个题看出来是单源最短路,N有点大,所以就用堆优化的Dijkstra了
因为有个对称,所以我们只需要把对角线以下的权值全部对称加到对角线以上,再从左上角走到对角线就OK了
上代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<queue> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 8 const int N=110; 9 const int mod=1000000009; 10 11 long long dis[N][N]; 12 int t[N][N],db[N][N]; 13 int n; 14 bool book[N][N]; 15 16 struct sik 17 { 18 int x,y,w;//坐标 权值 19 bool operator< (const sik & f) const//重载运算符 使优先队列为小根堆 20 { 21 return w>f.w; 22 } 23 }; 24 25 int Dijkstra() 26 { 27 int zx[4]={0,1,0,-1},zy[4]={1,0,-1,0};//走的方位 28 29 memset(dis,0x3f,sizeof(dis));//一堆初始化 30 memset(db,0,sizeof(db)); 31 memset(book,false,sizeof(book)); 32 int res=0,Min=0x3f3f3f3f; 33 34 priority_queue<sik> que;//优先队列 35 36 sik qu; 37 38 dis[1][1]=t[1][1]; 39 db[1][1]=1; 40 41 qu.x=1,qu.y=1,qu.w=t[1][1]; 42 que.push(qu); //把起点放进去 43 44 while(que.size()) 45 { 46 sik c=que.top(); 47 que.pop(); 48 int x=c.x,y=c.y; 49 50 if(dis[x][y]<=Min&&x+y==n+1) //到终点了 51 { 52 if(dis[x][y]==Min) res+=db[x][y]; 53 else 54 { 55 res=db[x][y]; 56 57 Min=dis[x][y]; 58 } 59 60 } 61 62 if(book[x][y]) continue;//当前点走过了 pass掉 63 book[x][y]=false; 64 65 for(int i=0;i<4;i++) 66 { 67 int x1=x+zx[i],y1=y+zy[i]; 68 69 if(book[x1][y1]||!x1||x1>n||!y1||y1>n) continue; 70 71 if(dis[x1][y1]>dis[x][y]+t[x1][y1]) 72 { 73 dis[x1][y1]=dis[x][y]+t[x1][y1]; 74 db[x1][y1]=db[x][y]; 75 76 sik o; 77 o.x=x1 , o.y=y1 , o.w=dis[x1][y1];//把当前这个点存进去 78 que.push(o); 79 } 80 else if(dis[x1][y1]==dis[x][y]+t[x1][y1]) 81 { 82 db[x1][y1]+=db[x][y]; 83 } 84 } 85 } 86 return res; 87 } 88 89 int main() 90 { 91 while(true) 92 { 93 memset(t,0,sizeof(t)); 94 scanf("%d",&n); 95 if(!n) return 0; 96 for(int i=1;i<=n;i++) 97 { 98 for(int j=1;j<=n;j++) 99 { 100 scanf("%d",&t[i][j]); 101 102 } 103 } 104 for(int i=1;i<=n;i++) 105 { 106 for(int j=1;j<=n-i;j++) 107 { 108 t[i][j]+=t[n-j+1][n-i+1];//把对角线以下的加上去 109 110 } 111 } 112 113 printf("%d\n",Dijkstra()); 114 } 115 return 0; 116 }
搞定
T3 :
不会
~END~